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?

+3


source to share


1 answer


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.

+3


source







All Articles