由于有时会stdin
和stdout
缓存printf
,因此不会执行scanf
和getchar
。我通常使用fflush(stdout)
刷新输出缓冲区,但代码因此而变得非常难以理解。如果我使用stdin
和stdout
设置setbuf(stdin, NULL)
和setbuf(stdout, NULL)
无缓冲,我会让我的程序表现更好还是更差?
答案 0 :(得分:7)
使#include <stdio.h>
int Maxmin(int a[][4], int row, int col) {
int i, j, max;
max = a[0][0];
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
if (a[i][j] > max)
max = a[i][j];
}
return max;
}
}
void main() {
int a[3][4] = {
{ 3, 87, 11, 23 },
{ 99, 78, 19, 44 },
{ 59, 60, 13, 14 }
};
int num;
num = Maxmin(a, 3, 4);
printf("%d\n", num);
}
或stdin
完全无缓冲可以使程序在处理大量文件输入/输出时表现更差。大多数I / O请求将按字节逐个进行系统调用。
请注意,缓冲不会导致stdout
,printf
和scanf
无法执行:getchar
输出到最终目的地只能被延迟,因此输入操作通过printf
或scanf
可能会在没有提示的情况下发生。
另请注意,将intput设置为unbuffered可能无法从终端生效,因为终端本身会通过getchar
或stty
执行自己的缓冲。
大多数C库都有一个hack,当从ioctl
读取需要从系统获取数据时会导致stdout
被刷新,但是这个行为没有在C标准中指定,所以有些库没有实现它。在输入操作之前以及诸如进度表之类的暂时性消息之后添加对stdin
的调用是安全的。在大多数情况下,最好让C启动程序根据与fflush(stdout);
和stdin
流关联的系统句柄类型确定适当的缓冲策略。常见的默认值是对设备进行行缓冲,并对文件进行完全缓冲,大小为stdout
。
要了解潜在的性能影响,请编译这个天真的BUFSIZ
程序:
ccat
时间程序执行多次复制大文件以最小化文件缓存副作用。
在Debian linux上,我得到了这个3.8MB文本文件的时间:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int c, size;
if (argc > 1) {
if (!strcmp(argv[1], "BUFSIZ"))
size = BUFSIZ;
else
size = strtol(argv[1], NULL, 0);
if (size == 0) {
/* make stdin and stdout unbuffered */
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
} else
if (size > 0) {
/* make stdin and stdout fully buffered */
setvbuf(stdin, NULL, _IOFBF, size);
setvbuf(stdout, NULL, _IOFBF, size);
} else {
/* make stdin and stdout line buffered */
setvbuf(stdin, NULL, _IOLBF, -size);
setvbuf(stdout, NULL, _IOLBF, -size);
}
}
while ((c = getchar()) != EOF) {
putchar(c);
}
return 0;
}
如你所见:
chqrlie@linux:~/dev/stackoverflow$ time wc w
396684 396684 3755392 w
real 0m0.072s
user 0m0.068s
sys 0m0.000s
chqrlie@linux:~/dev/stackoverflow$ time cat < w > ww
real 0m0.008s
user 0m0.000s
sys 0m0.004s
chqrlie@linux:~/dev/stackoverflow$ time ./ccat < w > ww
real 0m0.060s
user 0m0.056s
sys 0m0.000s
chqrlie@linux:~/dev/stackoverflow$ time ./ccat 0x100000 < w > ww
real 0m0.060s
user 0m0.058s
sys 0m0.000s
chqrlie@linux:~/dev/stackoverflow$ time ./ccat 0 < w > ww
real 0m5.326s
user 0m0.632s
sys 0m4.684s
chqrlie@linux:~/dev/stackoverflow$ time ./ccat -0x1000 < w > ww
real 0m0.533s
user 0m0.104s
sys 0m0.428s
和stdin
设置为无缓冲会导致程序速度减慢几乎 100 ,stdout
实用程序使用更快的API,执行时间 6 快。结论是:不要将cat
和stdin
设置为无缓冲,即使是中等大小的文件也会显着影响性能。