gpt4 book ai didi

c - 我应该在 C 中将 stdout 和 stdin 设置为无缓冲吗?

转载 作者:太空狗 更新时间:2023-10-29 15:23:41 27 4
gpt4 key购买 nike

因为 stdinstdout 有时缓冲 printf, scanfgetchar没有被执行。我通常使用 fflush(stdout) 刷新输出缓冲区,但代码可能因此变得非常不可读。如果我使用 setbuf(stdin, NULL)setbuf(stdout, NULL) 设置无缓冲的 stdinstdout 将我让我的程序表现得更好还是更差?

最佳答案

使 stdinstdout 完全无缓冲会使您的程序在处理大量文件输入/输出时性能更差。大多数 I/O 请求将分解为逐字节的系统调用。

注意缓冲不会导致printfscanfgetchar不执行:printf输出到最终目的地可能会被延迟,因此通过 scanfgetchar 的输入操作可能会在没有提示的情况下发生。

另请注意,将 intput 设置为无缓冲可能对终端无效,因为终端本身通过 sttyioctl 执行其自己的缓冲控制。

大多数 C 库都有一个 hack,当从 stdin 读取需要从系统获取数据时,会导致刷新 stdout,但 C 标准中未指定此行为,所以有些库没有实现它。在输入操作之前和进度表等临时消息之后添加对 fflush(stdout); 的调用是安全的。对于大多数用途,最好让 C 启动程序根据与 stdinstdout 流关联的系统句柄类型来确定适当的缓冲策略。常见的默认设置是对设备进行行缓冲,对文件进行大小为 BUFSIZ 的完全缓冲。

要了解潜在的性能影响,请编译这个简单的 ccat 程序:

#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;
}

多次复制大文件的程序执行时间,以最大限度地减少文件缓存的副作用。

在 Debian linux 机器上,我得到了一个 3.8MB 文本文件的这些计时:

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

如你所见:

  • stdinstdout 设置为无缓冲会导致程序速度减慢将近 100
  • 使用行缓冲会减慢 10 倍(因为行很短,平均 9 到 10 个字节)
  • 使用更大的缓冲区并没有显示出任何改善,时间差异并不显着,
  • 简单的实现速度非常快,但真正的 cat 实用程序使用更快的 API,执行时间快了 6 倍。

作为结论:不要将 stdinstdout 设置为无缓冲,即使是中等大小的文件也会显着影响性能。

关于c - 我应该在 C 中将 stdout 和 stdin 设置为无缓冲吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35239938/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com