467,142 Members | 1,227 Online

# Are system calls sometimes costlier than library calls?

 Hi all, I have two simple hello world programs one using printf()[a library func] and other using write() [syscall] --prog 1-- #include #include int main() { printf("Hello"); /* up to here write() isn't called, if u * give \n here then two write()s will * be called (?)*/ printf("World\n"); return 0; } --end-- --prog2-- #include int main() { write(1, "Hello", 5); write(1, "world\n", 6); return 0; } --end-- If u see the output of strace for prog1 --truncated-- .... munmap(0xb7fa0000, 115973) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fbc000 write(1, "HelloWorld\n", 11) = 11 exit_group(0) = ? -- end -- Its only making ONE write() system call for prog2 if u see strace --truncated-- .... mprotect(0xb7f50000, 4096, PROT_READ) = 0 munmap(0xb7f56000, 115973) = 0 write(1, "Hello", 5) = 5 write(1, "world\n", 6) = 6 exit_group(0) = ? --end-- Its making TWO syscalls. Hence in above example its clear that printf() is cheaper that write() contrary to what we might think. Why is that? Who is telling our program to combine to calls to printf() in a single wrtie() ? Is it the libc? Its certainly not compiler optimization as I compiled it with -O0 option. Thanks Omkar. Nov 6 '07 #1
• viewed: 2108
Share:
21 Replies
 In article <11**********************@e9g2000prf.googlegroups. com>, omkar pangarkar Hence in above example its clear that printf() is cheaper that write()contrary to what we might think. Why is that? Who is telling ourprogram to combine to calls to printf() in a single wrtie() ? Is itthe libc? I suggest you read about setbuf() -- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth Nov 6 '07 #2
 On Wednesday 07 Nov 2007 1:56 am omkar pangarkar wrote in article <11**********************@e9g2000prf.googlegroups. com>: Hi all, I have two simple hello world programs one using printf()[a library func] and other using write() [syscall] --prog 1-- #include #include int main() { printf("Hello"); /* up to here write() isn't called, if u * give \n here then two write()s will * be called (?)*/ printf("World\n"); return 0; } --end-- --prog2-- #include int main() { write(1, "Hello", 5); write(1, "world\n", 6); return 0; } --end-- If u see the output of strace for prog1 --truncated-- ... munmap(0xb7fa0000, 115973) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fbc000 write(1, "HelloWorld\n", 11) = 11 exit_group(0) = ? -- end -- Its only making ONE write() system call for prog2 if u see strace --truncated-- ... mprotect(0xb7f50000, 4096, PROT_READ) = 0 munmap(0xb7f56000, 115973) = 0 write(1, "Hello", 5) = 5 write(1, "world\n", 6) = 6 exit_group(0) = ? --end-- Its making TWO syscalls. Hence in above example its clear that printf() is cheaper that write() contrary to what we might think. Why are you worried about microoptimisation like these? Why is that? Who is telling our program to combine to calls to printf() in a single wrtie() ? Is it the libc? No. It's the compiler's optimiser. Its certainly not compiler optimization as I compiled it with -O0 option. BTW, write per se isn't likely to be a system call, but a wrapper to one. Nov 6 '07 #3
 On Tue, 06 Nov 2007 12:26:25 -0800, omkar pangarkar wrote: I have two simple hello world programs one using printf()[a library func] and other using write() [syscall] Hence in above example its clear that printf() is cheaper that write() contrary to what we might think. You're thinking too simply. printf() may well be doing a lot of processing before it calls write() (in fact, it is) which may be more expensive than an additional system call. You can't know which is faster by simply monitoring what is called. Why is that? Who is telling our program to combine to calls to printf() in a single wrtie() ? Is it the libc? Yes. Standard IO under almost all self-respecting C libraries is buffered. Its certainly not compiler optimization as I compiled it with -O0 option. Indeed not. I'd be upset if a compiler merged function calls like this. Why are you playing about with such a trivial low-gain optimisation? It's doubly pointless, as you're not even measuring the costs properly. Perhaps similar reasons to your faulty optimisation of the word "you" is at work? B. Nov 6 '07 #4
 santosh wrote On 11/06/07 15:32,: On Wednesday 07 Nov 2007 1:56 am omkar pangarkar wrote >[... two printf() calls generate just one write() ...]Why is that? Who is telling ourprogram to combine to calls to printf() in a single wrtie() ? Is itthe libc? No. It's the compiler's optimiser. What compiler does this? Libraries have been buffering output since time immemorial, but I've never seen a compiler merge two successive printf() calls into one call. (I've seen a compiler replace printf("Hello!\n") with puts("Hello!"), but never the transformation you describe.) -- Er*********@sun.com Nov 6 '07 #5
 On Nov 7, 1:38 am, Rob Kendrick Hence in above example its clear that printf() is cheaper that write() contrary to what we might think. You're thinking too simply. printf() may well be doing a lot of processing before it calls write() (in fact, it is) which may be more expensive than an additional system call. You can't know which is faster by simply monitoring what is called. Why is that? Who is telling our program to combine to calls to printf() in a single wrtie() ? Is it the libc? Yes. Standard IO under almost all self-respecting C libraries is buffered. Its certainly not compiler optimization as I compiled it with -O0 option. Indeed not. I'd be upset if a compiler merged function calls like this. Why are you playing about with such a trivial low-gain optimisation? It's doubly pointless, as you're not even measuring the costs properly. Perhaps similar reasons to your faulty optimisation of the word "you" is at work? B. This is not an attempt to optimize any code. I just need to know why such thing is happening and who is behind it? Nov 6 '07 #6
 "omkar pangarkar" On Tue, 06 Nov 2007 12:26:25 -0800, omkar pangarkar wrote: I have two simple hello world programs one using printf()[a library func] and other using write() [syscall] >>Indeed not. I'd be upset if a compiler merged function calls like this.Why are you playing about with such a trivial low-gain optimisation?It's doubly pointless, as you're not even measuring the costs properly.Perhaps similar reasons to your faulty optimisation of the word "you" isat work?B. This is not an attempt to optimize any code. I just need to know why such thing is happening and who is behind it? CRTL... as others have noted, it does buffering, and may choose to write output in larger chunks than what is initially passed to it. I suspect, at least in the case of printf, that this buffering is usually done until either: the buffer is full; a newline or similar is encountered. for file IO, it is less clear if/when exactly contents are written, but we do know at least that fflush and fclose cause contents to be written. I am not sure if in general fflush has lower-level effects (for example, if it also flushes OS-level file caching or commits changes to the underlying filesystem, or if it only ensures that changes are commited to the OS proper). this would mostly effect cases like, say, one calls fflush, and then very shortly following, the kernel crashes or the power fails or something... Nov 6 '07 #7
 On Tue, 06 Nov 2007 15:52:18 -0500, Eric Sosman wrote: What compiler does this? Libraries have been buffering output since time immemorial, but I've never seen a compiler merge two successive printf() calls into one call. (I've seen a compiler replace printf("Hello!\n") with puts("Hello!"), but never the transformation you describe.) stdio flushes its output buffer on every '\n'. #include int main() { char c, s[2] = ""; for (s[0] = 'A'; s[0] <= 'Z'; s[0]++) puts(c); for (c = 'a'; c <= 'z'; c++) putchar(c); putchar('\n'); return 0; } You will see that 26 write("A\n")..write("Z\n") syscalls are made, but only one write("abcdefghijklmnopqrstuvwxyz\n") syscall is made. Nov 7 '07 #8
 On Wed, 7 Nov 2007 01:21:35 +0000 (UTC), Tzy-Jye Daniel Lin What compiler does this? Libraries have beenbuffering output since time immemorial, but I've never seen a compilermerge two successive printf() calls into one call. (I've seen acompiler replace printf("Hello!\n") with puts("Hello!"), but never thetransformation you describe.) stdio flushes its output buffer on every '\n'. Not necessarily. A stream can be unbuffered, fully buffered, or line buffered (which is presumably what you think is always the case). setvbuf() can be used to control this behaviour. The C standard tells us that stderr is (initially) not fully buffered (i.e. line buffered or unbuffered), and stdin and stdout are fully buffered when a stream is determined not to be an interactive device. \begin{offtopic} On the OP's system, assuming it is some Unix-like system, stdout will be line buffered when connected to an interactive terminal, and fully buffered when connected to a non-interactive terminal. \end{offtopic} Martien -- | Martien Verbruggen | Louis Pasteur's theory of germs is ridiculous | fiction -- Pierre Pachet, Professor of | Physiology at Toulouse, 1872 Nov 7 '07 #9
 In article , Martien Verbruggen \begin{offtopic}On the OP's system, assuming it is some Unix-like system, stdoutwill be line buffered when connected to an interactive terminal, andfully buffered when connected to a non-interactive terminal.\end{offtopic} \begin{compulsoryCLCnitpickMode (*)} What's a "non-interactive terminal"? \end{compulsoryCLCnitpickMode} (*) Also known as "vying for points". Nov 7 '07 #10
 In article <47***********************@news.zen.co.uk>, Rob Kendrick Why are you playing about with such a trivial low-gain optimisation?It's doubly pointless, as you're not even measuring the costs properly.Perhaps similar reasons ... You would do well to Google the words "test", "experiment", and "learning". Nov 7 '07 #11
 Rob Kendrick I have two simple hello world programs one using printf()[alibrary func] and other using write() [syscall] >Hence in above example its clear that printf() is cheaper that write()contrary to what we might think. You're thinking too simply. printf() may well be doing a lot of processing before it calls write() (in fact, it is) which may be more expensive than an additional system call. You can't know which is faster by simply monitoring what is called. Yes you can. No one cares how long the "printf part is" - clearly the value of importance is the total time to return. > >Why is that? Who is telling our programto combine to calls to printf() in a single wrtie() ? Is it the libc? Yes. Standard IO under almost all self-respecting C libraries is buffered. >Its certainly not compiler optimization as I compiled it with -O0option. Indeed not. I'd be upset if a compiler merged function calls like this. Why are you playing about with such a trivial low-gain optimisation? It's doubly pointless, as you're not even measuring the costs properly. Perhaps similar reasons to your faulty optimisation of the word "you" is at work? I would imagine he is interested. And some people do run on systems where every clock cycle gained is important. if more people thought like that each and every time they check something in then maybe Word would open faster on a dual core duo with 3 gigs of ram than it did 10 years ago on a p3 with 128 megs. Nov 7 '07 #12
 Martien Verbruggen On Tue, 06 Nov 2007 15:52:18 -0500, Eric Sosman wrote: >> What compiler does this? Libraries have beenbuffering output since time immemorial, but I've never seen a compilermerge two successive printf() calls into one call. (I've seen acompiler replace printf("Hello!\n") with puts("Hello!"), but never thetransformation you describe.) stdio flushes its output buffer on every '\n'. Not necessarily. A stream can be unbuffered, fully buffered, or line buffered (which is presumably what you think is always the case). setvbuf() can be used to control this behaviour. The C standard tells us that stderr is (initially) not fully buffered (i.e. line buffered or unbuffered), and stdin and stdout are fully buffered when a stream is determined not to be an interactive device. \begin{offtopic} \end{offtopic} WTF is all this stuff? Postscript? Nov 7 '07 #13
 On Wed, 07 Nov 2007 14:34:19 +0100, Richard wrote: >You're thinking too simply. printf() may well be doing a lot ofprocessing before it calls write() (in fact, it is) which may be moreexpensive than an additional system call. You can't know which isfaster by simply monitoring what is called. Yes you can. No one cares how long the "printf part is" - clearly the value of importance is the total time to return. Knowing the total time to return is clearly different from knowing what is called. B. Nov 7 '07 #15
 "Richard" On Wed, 7 Nov 2007 01:21:35 +0000 (UTC),Tzy-Jye Daniel Lin >On Tue, 06 Nov 2007 15:52:18 -0500, Eric Sosman wrote: What compiler does this? Libraries have beenbuffering output since time immemorial, but I've never seen a compilermerge two successive printf() calls into one call. (I've seen acompiler replace printf("Hello!\n") with puts("Hello!"), but never thetransformation you describe.)stdio flushes its output buffer on every '\n'. Not necessarily. A stream can be unbuffered, fully buffered, or linebuffered (which is presumably what you think is always the case).setvbuf() can be used to control this behaviour.The C standard tells us that stderr is (initially) not fully buffered(i.e. line buffered or unbuffered), and stdin and stdout are fullybuffered when a stream is determined not to be an interactive device.\begin{offtopic}\end{offtopic} WTF is all this stuff? Postscript? looks like Latex to me. -- Chqrlie. Nov 8 '07 #16
 "Eric Sosman" On Wednesday 07 Nov 2007 1:56 am omkar pangarkar wrote >>[... two printf() calls generate just one write() ...]Why is that? Who is telling ourprogram to combine to calls to printf() in a single wrtie() ? Is itthe libc? No. It's the compiler's optimiser. What compiler does this? Libraries have been buffering output since time immemorial, but I've never seen a compiler merge two successive printf() calls into one call. (I've seen a compiler replace printf("Hello!\n") with puts("Hello!"), but never the transformation you describe.) Which compiler was that? Did it expand less trivial printf formats into a series of explicit calls to conversion functions? -- Chqrlie. Nov 8 '07 #17
 "Charlie Gordon" (I've seen a compiler replaceprintf("Hello!\n") with puts("Hello!"), but neverthe transformation you describe.) Which compiler was that? I think that GCC will do that, in some versions and at some optimization levels. Did it expand less trivial printf formats into a series of explicit calls to conversion functions? Haven't noticed it do that. -- char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[] ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+ 2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}} Nov 9 '07 #18
 Ben Pfaff "Eric Sosman" >(I've seen a compiler replaceprintf("Hello!\n") with puts("Hello!") Which compiler was that? I think that GCC will do that, in some versions and at some optimization levels. Some gcc's (the one have to hand) can't be stopped from doing it -- at least it seems to do it even with no optimisation turn on. -- Ben. Nov 9 '07 #19
 "Ben Bacarisse" "Charlie Gordon" >"Eric Sosman"
 "Charlie Gordon" Ben Pfaff >"Charlie Gordon"
 "Ben Bacarisse" "Ben Bacarisse" >Ben Pfaff (I've seen a compiler replace>printf("Hello!\n") with puts("Hello!")>Which compiler was that?I think that GCC will do that, in some versions and at someoptimization levels.Some gcc's (the one have to hand) can't be stopped from doing it -- atleast it seems to do it even with no optimisation turn on. My guess is they found a simple way to shine on comparison charts forsomeof the simpler tests, such as "total code size in statically linkedexecutable for simple hello.c". But static linking has become prettyrarethese days. That's a thought but it is not currently true in my hosted set up: $ls -l t.o t2.o -rw-r--r-- 1 ben ben 864 Nov 9 01:31 t.o -rw-r--r-- 1 ben ben 888 Nov 9 13:45 t2.o$ ls -l t t2 -rwxr-xr-x 1 ben ben 475988 Nov 9 13:44 t -rwxr-xr-x 1 ben ben 475476 Nov 9 13:45 t2 \$ nm t.o t2.o t.o: 00000000 T main U puts t2.o: 00000000 T main U printf They both have all the printf machinery linked in but it seems puts is longer than the one-line wrapper that printf probably requires. Something in the start-up or exit code path must require formatted printed in this set up. The motivation may have come from embedded uses, or some earlier version where this could be avoided, so your idea is quite reasonable. Here I get a 537k statically linked executable with a ton of link time warnings. It is so sad the Gnu libc has turned into so much bloated useless crap. hello.c should compile to just a few kilobytes of executable image with everything linked in and just the system call interface. How bad is it on the BSD font? -- Chqrlie. Nov 9 '07 #22

### This discussion thread is closed

Replies have been disabled for this discussion.