我的应用程序的核心大致如下:
size_t bufsize;
char* buf1;
size_t r1;
FILE* f1=fopen("/path/to/file","rb");
...
do{
r1=fread(buf1, 1, bufsize, f1);
processChunk(buf1,r1);
} while (!feof(f1));
...
(实际上,我有多个FILE*
和多个bufN
。)现在,我听说FILE
已准备好管理缓冲区(称为“流缓冲区”)所有这些,这种行为似乎是可以调整的:https://www.gnu.org/software/libc/manual/html_mono/libc.html#Controlling-Buffering。
如何重构上面的代码以放弃buf1
缓冲区并使用f1
的内部流缓冲区(将其设置为bufsize
)?
答案 0 :(得分:1)
如果您不想要不透明缓冲的I / O,请不要使用FILE *
。使用较低级别的API,您可以自己管理所有应用程序端缓冲,例如普通POSIX open()
和read()
。
答案 1 :(得分:0)
所以我已经阅读了一些C标准并运行了一些基准测试,这是我的发现:
1)按照上面的例子进行操作确实涉及不必要的内存中复制,这使得基于上述示例的简单cmp
程序的用户时间增加了大约两倍。然而,对于大多数IO重量级的程序来说,用户时间是微不足道的,除非文件的来源非常快。
但是,在内存文件源(Linux上为/dev/shm
)上,关闭FILE
缓冲(setvbuf(f1, NULL, _IONBF, 0);
)确实会产生一个很好且持续的速度提升约10-15%使用接近BUFSIZ
的buffsizes时的机器(再次,根据上面的代码片段测量IO重cmp
实用程序,我已经提到过,我在2个相同的700MB文件上测试了100次)。
2)虽然有一个用于设置FILE
缓冲区的API,但我没有找到任何用于阅读它的标准化API,所以我将坚持使用真实且经过测试的方法,但是关闭FILE
缓冲区(setvbuf(f1, NULL, _IONBF, 0);
)
(但我想我可以通过将自己的缓冲区设置为带有_IONBF模式选项的FILE流缓冲区来解决我的问题(=关闭缓冲),然后我可以通过FILE结构中的一些非标准化指针来访问它。 )