是否应将stdout和stdin设置为在C中不缓冲? [英] Should I set stdout and stdin to be unbuffered in C?
问题描述
由于 stdin
和 stdout
有时会缓冲 printf
, scanf
和 getchar
未执行。我通常使用 fflush(stdout)
刷新输出缓冲区,但是代码可能因此变得非常不可读。如果我使用 setbuf(stdin,NULL)$ c将
stdin
和 stdout
设置为无缓冲$ c>和 setbuf(stdout,NULL)
我会让程序性能更好还是更差?
Because of stdin
and stdout
buffering sometimes printf
, scanf
and getchar
are not executed. I usually flush output buffer using fflush(stdout)
but code can become very unreadable because of that. If I set stdin
and stdout
unbuffered using setbuf(stdin, NULL)
and setbuf(stdout, NULL)
will I make my program perform better or worse?
推荐答案
完全不缓冲地制作 stdin
或 stdout
会使程序在处理较大内容时性能变差文件输入/输出的数量。大多数I / O请求将按系统逐字节分解为系统调用。
Making stdin
or stdout
completely unbuffered can make your program perform worse if it handles large quantities of input / output from and to files. Most I/O requests will be broken down as system calls on a byte by byte basis.
请注意,缓冲不会导致 printf
, scanf
和 getchar
不执行: printf
输出到最终目标的时间可能会延迟,因此通过 scanf
或 getchar
进行的输入操作可能不会
Note that buffering does not cause printf
, scanf
and getchar
to not be executed: printf
output to the final destination can just be delayed, so the input operation via scanf
or getchar
may occur without a prompt.
还要注意,将输入设置为未缓冲可能在终端上无效,因为终端本身执行自己的缓冲,该缓冲通过 stty
或 ioctl
。
Note also that setting intput as unbuffered may not be effective from the terminal because the terminal itself performs its own buffering controlled via stty
or ioctl
.
大多数C库都有一个导致 stdin
读取时要刷新的> stdout 需要从系统获取数据,但是C标准中未指定此行为,因此某些库不要实现它。在输入操作之前和进度表等临时消息之后,将调用添加到 fflush(stdout);
是安全的。对于大多数目的,最好让C启动根据与 stdin
和 stdout <相关的系统句柄的类型来确定适当的缓冲策略。 / code>流。常见的默认设置是对设备进行行缓冲,对文件进行完全缓冲,其大小为
BUFSIZ
。
Most C libraries have a hack that causes stdout
to be flushed when reading from stdin
requires getting data from the system, but this behavior is not specified in the C Standard, so some libraries do not implement it. It is safe to add calls to fflush(stdout);
before input operations, and after transitory messages such as progress meters. For most purposes, it is best to let the C startup determine the appropriate buffering strategy depending upon the type of system handle associated with the stdin
and stdout
streams. The common default is line buffered for devices and fully buffered with a size of BUFSIZ
for files.
要想知道潜在的性能影响,请编译以下简单的 ccat
程序:
To get an idea of the potential performance hit, compile this naive ccat
program:
#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;
}
时间程序执行多次复制大文件,以最大程度地减少文件缓存的副作用。
Time program execution copying a large file several times to minimize file caching side effects.
在Debian linux上,我得到了3.8MB文本文件的计时:
On a Debian linux box I get these timings for a 3.8MB text file:
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
和stdout
到未缓冲会导致程序减慢几乎 100 的速度, - 使用行缓冲会使速度减慢 10 的因数(因为行很短,平均9到10个字节)
- 使用较大的缓冲区不会显示任何改善,时序差异不会
- 天真的实现速度非常快,但是真正的
cat
实用工具针对 6 使用了更快的API
- setting
stdin
andstdout
to unbuffered causes the program to slow down by a factor of almost 100, - using line buffering slows down by a factor of 10 (because lines are short, 9 to 10 bytes on average)
- using a larger buffer does not show any improvement, the timing difference is not significant,
- the naive implementation is quite fast, but the real
cat
utility uses faster APIs for 6 times faster execution times.
结论:请勿设置 stdin
stdout
设置为无缓冲,即使对于中等大小的文件,也会显着影响性能。
As a conclusion: do not set stdin
and stdout
to unbuffered, it will impact performance significantly for even moderately large files.
这篇关于是否应将stdout和stdin设置为在C中不缓冲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!