puts() vs printf()

D

Debaser

I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation. The author uses
void main() so I'm not sure what to think. Given today's hardware and
compiler optimizations I have no idea if it even matters. I'm not very
good at modern-day assembly, so I can't compare it that way.
I've generally steered away from the puts-gets I/O functions in the
past. I don't know why this is the case...maybe it has to do with
consistency as I don't always want the newline automatically output.

What's the word?

Thanks.

p.s. The book is by Herb Schlidt (or something similar) if that's any
indication.
 
W

Walter Roberson

I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:
puts("Some random text");

printf("Some random text\n");
[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation.

printf() -likely- calls va_init() unconditionally, but after that
there would be no arguments to process as there are no format
elements. Calling or not calling va_init() would be a constant time
factor, probably nearly undetectable.

printf() must examine each character at least once in order to
figure out that it is -not- a format character. If it is using
putc() to output characters, then in theory it could just output
each character immediately. It needs to test each character to
see if it is \0 anyhow, but two comparisons per character
instead of one might detectable on long enough strings.

If printf() is implimented by printing the entire string into a buffer
first, such as by calling sprintf() and then outputing the resulting
string, then the overhead of doing that would likely be detectable.

If you think about it, you will see that there is effectively
no way for printf() to do -less- work than puts() does: if there
were then puts() would use that method instead. The questions then
becomes one of QOI (Quality of Implementation), together with
a question about instruction set architecture. In theory, two
tests per loop is not *necessarily* any slower than one, as there
could be an instruction that was effectively "move string until
delimeter", or the two tests might be overlapped, or the tight
loop could be micro-optimized. (The instruction set visible to
the programming level is often not the instruction set used
internally: microcoding is quite common.)
 
E

Eric Sosman

Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation. The author uses
void main() so I'm not sure what to think. Given today's hardware and
compiler optimizations I have no idea if it even matters. I'm not very
good at modern-day assembly, so I can't compare it that way.
I've generally steered away from the puts-gets I/O functions in the
past. I don't know why this is the case...maybe it has to do with
consistency as I don't always want the newline automatically output.

puts(str) is usually faster than printf(str) because it
doesn't need to search through `str' for conversion specifications
like "%d". (Note that if `str' contains anything that looks
even vaguely like a conversion specification, printf(str) will
be in deep trouble -- printf("category\tcount\t%frequency\n")
is most definitely a no-no.)

That said, the difference is likely to be so small that it's
unnoticeable, probably even so small that it will be difficult
to measure. Consider: You've got actual data output operations
going on, in order to deliver the printf()/puts() characters to
their destination -- disk file, pipe, cable modem with WhizFiber,
or whatever. All of these channels are VASTLY slower than the
CPU that executes the function call; by switching to the "more
efficient" variety you may be doing nothing more than increasing
the iteration count of the idle loop.

A friend of mine once described this sort of optimization as
"Cleaning the bottle tops off the beach so the sand will be nice
and clean around the beached whale carcases." Ponder that.
> p.s. The book is by Herb Schlidt (or something similar) if that's any
> indication.

I, personally, have never read any of Herr Schildt's works.
Others have, and have commented on them more perspicaciously than
I could; see, for example,

http://www.lysator.liu.se/c/schildt.html

It has been observed that Schildt's "The Annotated C Standard"
costs less than the Standard itself, and it has been opined that
the difference in price reflects the value of the annotations.
 
B

Barry Schwarz

I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since

It is strictly a quality of implementation issue. I personally
believe the assertion is generally true but that and a quarter still
won't buy you a cup of coffee.
printf() uses vargs, but I'd like some confirmation. The author uses

Not because of variable arguments but because puts is a single minded
function (send an already formatted string to stdout) while printf has
so many bells and whistles that it "should" take more time to figure
out what it is you really want to do is the same.

It is also possible that some clever library writer decided this
degenerative use of printf is so common that a special check is made
early in the code and therefore the difference is immeasurably small.
void main() so I'm not sure what to think. Given today's hardware and

A lot of books do unfortunately but it still serves as a reminder that
the author is prone to carelessness.
compiler optimizations I have no idea if it even matters. I'm not very
good at modern-day assembly, so I can't compare it that way.
I've generally steered away from the puts-gets I/O functions in the
past. I don't know why this is the case...maybe it has to do with
consistency as I don't always want the newline automatically output.

What's the word?

Thanks.

p.s. The book is by Herb Schlidt (or something similar) if that's any
indication.

Be afraid, be very afraid!


Remove del for email
 
S

Stephen Sprunk

Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation. The author uses
void main() so I'm not sure what to think. Given today's hardware and
compiler optimizations I have no idea if it even matters.

A modern compiler will notice when a single argument to printf()
contains no format specifiers and replace the call with puts() --
assuming it can strip the final '\n' at compile time.

I personally prefer using printf() for all output because then I don't
have to deal with forgetting the implicit '\n' that puts() adds.

S
 
C

CBFalconer

Debaser said:
I've recently read in one of my old C books that puts() is a
better function call with regard to performance than printf()
in the following situation:

puts("Some random text");
vs.
printf("Some random text\n");
.... snip ...

p.s. The book is by Herb Schlidt (or something similar) if
that's any indication.

It is. BullSchildt is normally error infested. In this particular
case he is right. This is analagous to undefined behaviour -
sometimes you get the expected result.
 
J

jaysome

On Wed, 23 Aug 2006 21:33:08 -0400, Eric Sosman


[snip]
It has been observed that Schildt's "The Annotated C Standard"
costs less than the Standard itself, and it has been opined that
the difference in price reflects the value of the annotations.

It's actually "The Annotated ANSI C Standard", ISBN 0-07-881952-0.

It has the text of the ANSI/ISO 9899-1990 standard on the left-hand
pages and Herbert's comments on the right-hand pages.

Unless I'm in need of a good laugh, I close my right eye when reading
this book. Both eyes open or not, it makes for real good reading--well
worth the price--providing you can find it.

It's unfortunate that someone like Steve Summit didn't write this
book.

Regards
 
S

Schraalhans Keukenmeester

Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation. The author uses
void main() so I'm not sure what to think. Given today's hardware and
compiler optimizations I have no idea if it even matters. I'm not very
good at modern-day assembly, so I can't compare it that way.
I've generally steered away from the puts-gets I/O functions in the
past. I don't know why this is the case...maybe it has to do with
consistency as I don't always want the newline automatically output.

What's the word?

Thanks.

p.s. The book is by Herb Schlidt (or something similar) if that's any
indication.

When in doubt of relative speed of alternatives, you could put both
solutions to the test. A longer test run probably is more accurate than
a single loop.

#define RUNS 1000000UL
int main (void)
{
unsigned long i;
for (i=0;i<RUNS;i++) {
printf("stuff\n");
// puts("stuff"); alternate with printf.
}
return 0;
}

Then compile and run the program. If your OS has no standard timer you
could use a built-in timer in the program, or time manually (but then
you really want long runs for reliability/accuracy). *nix offers you the
command time which shows you user, system and real time used by the
program. Simply recompile with the different options enabled and go.
$ time ./a.out
should do the trick, where a.out is the default binary file name created
by gcc. Output-related measurements are more accurate/reliable when the
output is redirected to the bitbucket.

I just ran this example on my own system:

1 mln runs with printf() // 8 char string (or 9, including \n)
time ( ./a.out &> /dev/null )
real 0m1.214s
user 0m1.207s
sys 0m0.006s

1 mln runs with puts() // 8 char string
time ( ./a.out &> /dev/null )
real 0m0.552s
user 0m0.546s
sys 0m0.004s

So puts() is substantially faster in this case. With longer strings the
relative difference increases.

time ( ./a.out &> /dev/null ) // printf(), 100 char string
real 0m4.174s
user 0m4.128s
sys 0m0.042s

time ( ./a.out &> /dev/null ) // puts(), 100 char string
real 0m1.484s
user 0m1.443s
sys 0m0.036s

I wonder how often one has to output a gazillion const strings making
the difference relevant though...

Rgds
Sh
 
J

jaapsch

Schraalhans said:
Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");
vs.
printf("Some random text\n");

When in doubt of relative speed of alternatives, you could put both
solutions to the test. [snip]
1 mln runs with printf() // 8 char string (or 9, including \n)
time ( ./a.out &> /dev/null )
real 0m1.214s
user 0m1.207s
sys 0m0.006s

1 mln runs with puts() // 8 char string
time ( ./a.out &> /dev/null )
real 0m0.552s
user 0m0.546s
sys 0m0.004s

So puts() is substantially faster in this case. With longer strings the
relative difference increases.

I wonder how often one has to output a gazillion const strings making
the difference relevant though...

I would have thought that in this case (where the string to be printed
is a supplied literal string), the compiler would be able to optimise
it into a puts() call. I suppose it would first have to replace any
"%%" with "%" and so on.
As you said, it is likely a micro-optimisation that is probably not
worth the effort for compiler writers.
 
R

Robert Gamble

jaapsch said:
Schraalhans said:
Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");
vs.
printf("Some random text\n");

When in doubt of relative speed of alternatives, you could put both
solutions to the test. [snip]
1 mln runs with printf() // 8 char string (or 9, including \n)
time ( ./a.out &> /dev/null )
real 0m1.214s
user 0m1.207s
sys 0m0.006s

1 mln runs with puts() // 8 char string
time ( ./a.out &> /dev/null )
real 0m0.552s
user 0m0.546s
sys 0m0.004s

So puts() is substantially faster in this case. With longer strings the
relative difference increases.

I wonder how often one has to output a gazillion const strings making
the difference relevant though...

I would have thought that in this case (where the string to be printed
is a supplied literal string), the compiler would be able to optimise
it into a puts() call. I suppose it would first have to replace any
"%%" with "%" and so on.
As you said, it is likely a micro-optimisation that is probably not
worth the effort for compiler writers.

Actually, gcc does do just that for string literals that end with a
newline and don't contain %.

Robert Gamble
 
E

Eric Sosman

jaapsch said:
I would have thought that in this case (where the string to be printed
is a supplied literal string), the compiler would be able to optimise
it into a puts() call. I suppose it would first have to replace any
"%%" with "%" and so on.
As you said, it is likely a micro-optimisation that is probably not
worth the effort for compiler writers.

Compiler writers obey strange masters.

A former colleague who had labored as a compiler writer
for a large computer company (now defunct) told me he *did*
put this transformation into their compiler. Why? Because
parts of the SPEC benchmark suite used many "non-converting"
printf() calls, and by switching to puts() they raised their
SPEC scores without the silly bother of needing to make the
machine any faster. The improvement was only a milliwhisker
or two, but a computer maker will jump through a lot of hoops
for the appearance of greater speed ("As measured on industry-
standard benchmarks!").

Standardized benchmarks can be helpful measurement tools,
but they're rotten policy drivers.
 
C

CBFalconer

Eric said:
.... snip ...

A former colleague who had labored as a compiler writer
for a large computer company (now defunct) told me he *did*
put this transformation into their compiler. Why? Because
parts of the SPEC benchmark suite used many "non-converting"
printf() calls, and by switching to puts() they raised their
SPEC scores without the silly bother of needing to make the
machine any faster. The improvement was only a milliwhisker
or two, but a computer maker will jump through a lot of hoops
for the appearance of greater speed ("As measured on industry-
standard benchmarks!").

Yet it did make that system faster in general. It also probably
reduced the object size of some fraction of programs. The fact
that its effects were exagerrated by the benchmark is just a bonus
:)
 
F

Flash Gordon

Eric said:
Compiler writers obey strange masters.

Standardized benchmarks can be helpful measurement tools,
but they're rotten policy drivers.

In my opinion it is not a completely silly optimisation to do, it is
just one more example of strength reduction, although not necessarily
one that is high priority to implement. However, if it has a noticeable
effect on benchmark results then the benchmark is possibly not as good
as it should be.
 
D

Default User

Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");


I would use puts() in this case, just because it's the routine made for
that operation. Less typing too. With no conversions to perform, I'd
only use printf() if I didn't want an automatic newline.




Brian (clarity not speed is the determing factor)
 
S

Schraalhans Keukenmeester

Stephen said:
Debaser said:
I've recently read in one of my old C books that puts() is a better
function call with regard to performance than printf() in the
following situation:

puts("Some random text");

vs.

printf("Some random text\n");

[Read: no formatting.]
Would anyone please confirm or deny this? It makes sense since
printf() uses vargs, but I'd like some confirmation. The author uses
void main() so I'm not sure what to think. Given today's hardware and
compiler optimizations I have no idea if it even matters.

A modern compiler will notice when a single argument to printf()
contains no format specifiers and replace the call with puts() --
assuming it can strip the final '\n' at compile time.

I personally prefer using printf() for all output because then I don't
have to deal with forgetting the implicit '\n' that puts() adds.

S
Slightly wandering OT: Tried my example (see my other response in this
thread) with gcc optimization enabled and ONLY when the string is a
literal or a #defined constant it looks as if execution times are
identical, which may be (and probably is) indicative of printf() being
replaced by the faster puts(). Declaring the string (even as const)
*char does not convince gcc to use puts() in stead of printf(), at least
not here.

Would you say that gcc is a modern or old compiler based on this?
Sh.
 
R

Racaille

Robert said:
Actually, gcc does do just that for string literals that end with a
newline and don't contain %.

gcc also changes 'printf("%s\n", str)' into 'puts(str)'.

$ gcc -S -O2 -x c - -o -
#include <stdio.h>
extern char *p;
int main(void) { printf("%s\n", p); return 0; }
^D .file ""
.text
.p2align 2,,3
..globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
subl $28, %esp
pushl p
call puts
xorl %eax, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 3.4.4 [FreeBSD] 20050518"
 
C

CBFalconer

Flash said:
.... snip ...



In my opinion it is not a completely silly optimisation to do, it
is just one more example of strength reduction, although not
necessarily one that is high priority to implement. However, if
it has a noticeable effect on benchmark results then the
benchmark is possibly not as good as it should be.

If that optimization manages to remove ALL references to printf,
then there is no need to load all that monstrous output
interpreter, and there can be significant reduction in the size of
the output code.

Fighting bloat at every turn :)
 
S

Stephen Sprunk

Schraalhans Keukenmeester said:
Slightly wandering OT: Tried my example (see my other response in this
thread) with gcc optimization enabled and ONLY when the string is a
literal or a #defined constant it looks as if execution times are
identical, which may be (and probably is) indicative of printf() being
replaced by the faster puts(). Declaring the string (even as const)
*char does not convince gcc to use puts() in stead of printf(), at
least
not here.

Would you say that gcc is a modern or old compiler based on this?
Sh.

My experience plus Racaille's report in another post lead me to say it's
modern, i.e. doing something reasonably clever as I described. It's
curious that it doesn't convert a printf(char*) to puts(char*) but does
with literals, but there may be some reason for that or it might be a
bug (at least in your version).

S
 
C

CBFalconer

Stephen said:
.... snip ...

My experience plus Racaille's report in another post lead me to
say it's modern, i.e. doing something reasonably clever as I
described. It's curious that it doesn't convert a printf(char*)
to puts(char*) but does with literals, but there may be some
reason for that or it might be a bug (at least in your version).

It can't. The output of the two statements is different.
 
R

robertwessel2

jaysome said:
On Wed, 23 Aug 2006 21:33:08 -0400, Eric Sosman


[snip]
It has been observed that Schildt's "The Annotated C Standard"
costs less than the Standard itself, and it has been opined that
the difference in price reflects the value of the annotations.


That and the fact that the middle of 7.6.9.1 is omitted because the
preceding page is duplicated.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top