Putc and putchar performance?
I've always thought that calling putc is several times faster than puts or printf. To print "hello", for example in a real program, I will always use puts or printf, but now I am writing a program that generates C code, so I was wondering if I should generate code like putchar('h'); putchar('e') ...
, because I first thought it should be faster ... But I did a test that gave a very interesting result. The compiler is GCC.
#include <stdio.h>
#include <time.h>
int main() {
time_t timer;
FILE *f;
int i;
f = fopen("out.txt", "w");
#define START_TIMER(TIMER) TIMER = clock()
#define ELAPSED_TIME(TIMER)\
(double)(clock() - TIMER) / (double)CLOCKS_PER_SEC
enum { NUM_ITERS = 9999999 };
START_TIMER(timer);
for (i = 0; i < NUM_ITERS; i++) {
putc('h', f);
putc('e', f);
putc('l', f);
putc('l', f);
putc('o', f);
putc('\n', f);
}
printf("%.3f\n", ELAPSED_TIME(timer));
START_TIMER(timer);
for (i = 0; i < NUM_ITERS; i++) {
fputs("hello", f);
}
printf("%.3f\n", ELAPSED_TIME(timer));
START_TIMER(timer);
for (i = 0; i < NUM_ITERS; i++) {
fprintf(f, "hello\n");
}
printf("%.3f\n", ELAPSED_TIME(timer));
return 0;
}
result without optimization:
4.247 1.013 1.195
result with optimization (-O2):
0.910 1.184 1.315
result with optimization (-O3):
0.920 1.158 1.311
So the call to putc is several times slower than puts of printf when naively executed without optimization. First, I am curious why this is so. Second, how should I follow the C program code?
source to share
Your intuition for what should be faster is wrong. Typically, putc
/ putchar
will have a lot of overhead per byte, as there is a whole function call loop, potential stdio ( stdout
) stream blocking , etc. For every byte. On the other hand, functions like printf
or puts
have more overhead for each call than putc
(for example, printf
should handle a format string and puts
should call strlen
or the equivalent), but that overhead only happens once, no matter how many bytes you write. The actual write can be done as a bulk copy to the buffer FILE
or as a bulk write to the underlying file (if FILE
unbuffered).
As far as how the optimization levels are affected -O0
, it probably has a lot more overhead, making a function call that gets optimized at higher optimization levels.
source to share