From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 10c696,9bedf54b4be9359b,start X-Google-Attributes: gid10c696,public X-Google-Thread: 103376,9bedf54b4be9359b,start X-Google-Attributes: gid103376,public From: Markus Kuhn Subject: Buffered I/O with GNAT on Linux Date: 1998/06/14 Message-ID: <3583B587.2DB4EDBC@cl.cam.ac.uk>#1/1 X-Deja-AN: 362513912 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii Organization: Cambridge University, Computer Laboratory Mime-Version: 1.0 Newsgroups: comp.lang.ada,comp.os.linux.development.apps Date: 1998-06-14T00:00:00+00:00 List-Id: The GNAT 3.10p reference manual claims that the Ada.Text_IO is performed over the stream buffering provided by the C library. However if I execute under Linux (RH 4.1 and 5.0) the test program ----------------------------------------------- with Ada.Text_IO; use Ada.Text_IO; procedure Strange is begin for I in 1 .. 10 loop Put("Hello "); end loop; New_Line; end Strange; ----------------------------------------------- and start it with strace to log the system calls, then I get $ strace ./strange >/dev/null [...] write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "Hello ", 6) = 6 write(1, "\n", 1) = 1 _exit(0) = ? which clearly shows that there is no buffering going on and every single Ada.Text_IO call seems to result in a write system call. C is much more efficient here: $ cat notstrange.c #include int main() { int i; for (i = 0; i < 10; i++) printf("Hello "); printf("/n"); return 0; } $ strace ./notstrange >/dev/null [...] write(1, "Hello Hello Hello Hello Hello He"..., 62) = 62 munmap(0x400ac000, 4096) = 0 _exit(0) = ? The lack of buffering is especially troubelsome for Linux users, because Linux 2.0 does not have any NFS buffering in the kernel. Every single write() results immediately in a remote procedure call to the NFS server. If the NFS server does in addition synchronous writes (like the DEC one I have to use here does), then a single Put instruction under Ada requires several hundred milliseconds to execute. This causes programs such as gnatbind and gnatlink to execute over 50 times slower if the accessed files are Linux NFS mounted. Compiling the above test program with gnatmake takes around 55 seconds in my NFS mounted home directory, but only around one second in /tmp, which is a local harddisk that enjoys kernel block buffering. Is there any trick to get GNAT 3.10p to really use the libc stream buffering, especially for gnatlink and gnatbind? Markus -- Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK email: mkuhn at acm.org, home page: