3

我一直认为多次调用 putc 比 puts 或 printf 快。以打印“hello”为例,在实际程序中我总是使用puts或printf,但现在我正在编写一个生成C代码的程序,所以我想知道是否要生成代码,putchar('h'); putchar('e') ...因为我首先认为它应该更多快点。但是我进行了一个测试,结果非常有趣。编译器是 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;
}

未经优化的结果:

4.247 1.013 1.195

优化结果(-O2):

0.910 1.184 1.315

优化结果(-O3):

0.920 1.158 1.311

因此,在没有优化的情况下天真地执行时,多次调用 putc 比 printf 的 puts 慢。首先,我很好奇为什么会这样。其次,对于程序生成的 C 代码,我应该遵循哪种方式?

4

1 回答 1

5

您对应该更快的直觉是错误的。通常,putc/putchar每写入一个字节都会有很多开销,因为每个字节都有一个完整的函数调用周期、潜在的 stdio 流 ( stdout) 锁定等。另一方面,函数喜欢printf每次调用有更多puts的开销(例如必须处理格式字符串,并且必须调用或等效),但无论您正在编写多少字节,这种开销只会发生一次。实际写入可以作为对's 缓冲区的大容量复制,或对基础文件的大容量写入(如果没有缓冲)。putcprintfputsstrlenFILEFILE

至于优化级别如何影响这一点,-O0在进行更高优化级别优化的函数调用方面可能会有更多开销。

于 2014-10-06T23:16:22.513 回答