由于stdin
和stdout
缓冲有时printf
,scanf
和getchar
不执行。我通常使用fflush(stdout)
刷新输出缓冲区,但由于这种情况,代码可能变得非常不可读。如果我使用setbuf(stdin, NULL)
和setbuf(stdout, NULL)
来设置stdin
和stdout
无缓冲区,我会让我的程序表现更好还是更差?我应该设置标准输出和标准输入缓冲在C?
3
A
回答
6
制作stdin
或stdout
完全无缓冲会使您的程序在处理大量来自和去往文件的输入/输出时性能更差。大多数I/O请求将在逐字节的基础上被分解为系统调用。
注意,缓冲不引起printf
,scanf
和getchar
到不被执行:可以只被延迟printf
输出到最终目标,所以不带提示,可能会发生通过scanf
或getchar
输入操作。
另请注意,将输入设置为无缓冲可能无法从终端生效,因为终端本身执行自己的缓冲,通过stty
或ioctl
控制。
大多数C库有一个黑客,导致stdout
从stdin
需要从系统中获取数据时被刷新,但这种行为没有在C标准中指定,所以一些库不实现它。在输入操作之前以及暂时性消息(如进度表)之前添加对fflush(stdout);
的呼叫是安全的。对于大多数用途而言,最好让C启动根据与stdin
和stdout
流关联的系统句柄的类型确定适当的缓冲策略。常见的默认设置是为设备缓冲行,并为文件完全缓冲,大小为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的文本文件:
[email protected]:~/dev/stackoverflow$ time wc w
396684 396684 3755392 w
real 0m0.072s
user 0m0.068s
sys 0m0.000s
[email protected]:~/dev/stackoverflow$ time cat <w> ww
real 0m0.008s
user 0m0.000s
sys 0m0.004s
[email protected]:~/dev/stackoverflow$ time ./ccat <w> ww
real 0m0.060s
user 0m0.056s
sys 0m0.000s
[email protected]:~/dev/stackoverflow$ time ./ccat 0x100000 <w> ww
real 0m0.060s
user 0m0.058s
sys 0m0.000s
[email protected]:~/dev/stackoverflow$ time ./ccat 0 <w> ww
real 0m5.326s
user 0m0.632s
sys 0m4.684s
[email protected]:~/dev/stackoverflow$ time ./ccat -0x1000 <w> ww
real 0m0.533s
user 0m0.104s
sys 0m0.428s
正如你可以看到:
- 设置
stdin
和stdout
非缓冲导致程序变慢几乎相差, - 使用行缓冲减慢了因子(因为线短,9〜10字节平均)使用较大的缓冲液没有表现出任何改善
- ,定时差不显著,
- 幼稚实现是相当快的,但真正
cat
实用程序使用执行时间更快,速度更快的API。
这样的结论:没有设置stdin
和stdout
非缓冲,它会为中等甚至大型文件显著影响性能。
相关问题
- 1. C中的标准输入和输出标准输入和输出
- 2. 我应该需要什么节点JS标准输入和标准输出
- 3. 打开Windows控制台的标准输入/标准输出/标准输入/输出为win32和win64在C
- 4. C++从标准输入和标准输出读取
- 5. 红宝石IO.popen标准输出缓冲
- 6. 标准输出缓冲甚至fflush
- 7. Python:清除标准输入缓冲区
- 8. 非缓冲标准输入读取
- 9. 什么是标准输入缓冲区?
- 10. 写入标准输出并从标准输入读取C
- 11. 标准输入/输出在C#过程
- 12. Linux的标准输入,标准输出,标准错误
- 13. bash:冲洗标准输入(标准输入)
- 14. 标准输入/输出流
- 15. C:重定向标准输入,标准输出到管道
- 16. C++写的标准输入数据,并从标准输出
- 17. Docker执行与OpenSSL和标准输入,标准输出
- 18. 转储外部程序的标准输入和标准输出
- 19. 重定向进程标准输入和标准输出到netcat
- 20. Python:同时使用标准输入和标准输出
- 21. 标准输出/标准输入和参数
- 22. 从标准输入在C#
- 23. 如何在C++中打印缓冲区到标准输出?
- 24. 包括标准输入输出和stddef
- 25. 当我关闭标准输入的缓冲和对ungetc函数标准输入发生了什么?
- 26. C在提交之前读取标准输入缓冲区
- 27. 在c中重定向标准输出,然后重置标准输出
- 28. 如何处理标准输入到标准输出在PHP?
- 29. 命名管道,chaning标准输入,在标准输出叉()
- 30. 写入输出流3(标准输出或标准错误)