了解 fwrite() 的缓冲行为
Understanding buffering behavior of fwrite()
我正在使用函数调用fwrite()
将数据写入Linux上的管道。
早些时候,fwrite()
被反复调用小块数据(平均20字节),缓冲留给fwrite()
。 进程上的 Strace 显示一次写入 4096 字节的数据。
事实证明,这个写作过程是我程序的瓶颈。因此,我决定将代码中的数据缓冲为 64KB 的块,然后使用 fwrite()
一次写入整个块。我使用 setvbuf()
将 FILE* 指针设置为"无缓冲"。
性能改进并不像我预期的那么显着。
更重要的是,strace
输出显示数据一次仍写入 4096 字节。有人可以向我解释这种行为吗?如果我调用具有 64KB 数据的fwrite()
,为什么它一次只写入 4096 字节?
是否有替代使用 FILE* 指针将数据写入管道的fwrite()
?
4096 来自作为管道基础的 Linux 机器。它发生在两个地方。一是管道的容量。容量是旧版 Linux 上的一个系统页面,在 32 位 i386 机器上为 4096 字节。(在更现代的Linux版本上,容量为64K。
您将遇到 4096 字节问题的另一个地方是定义的常量PIPE_BUF
,保证以原子方式处理的字节数。在 Linux 上,这是 4096 字节。此限制的含义取决于是否已将管道设置为阻止还是非阻塞。为所有血腥的细节做一个man -S7 pipe
。
如果您尝试以高速率交换大量数据,您可能需要重新考虑管道的使用。你使用的是 Linux 机器,所以共享内存是一种选择。可以使用管道发送相对少量的数据作为信号机制。
如果要更改缓冲行为,则必须在fopen
之后立即执行此操作(或任何 I/O 之前,对于标准文件句柄stdin
、stdout
、stderr
)。 您也不想禁用缓冲并尝试自己管理缓冲区;相反,请指定要setvbuf
的 64K 缓冲区,以便可以正确使用它。
如果确实要手动管理缓冲,请不要使用 stdio
;请使用较低级别的 open
、write
和 close
调用。
- 如何使用原子指针执行双缓冲
- 消费者和生产者问题的双重缓冲
- 如何检测是否在缓冲绘画动画中绘制最后一帧?
- 我似乎无法修改帧缓冲
- 如何在C++中写入 1000 个文件时有效地缓冲
- 帧缓冲纹理变为白色(片段着色器不会影响它)
- 我是否使用双缓冲?
- OpenGL:使用实例化绘图与我正在绘制的帧缓冲进行绘制
- 如何强制文件描述符缓冲我的输出
- 将fwrite转换为C++类型代码以写入二进制文件
- 在数据写入磁盘之前,fwrite 会阻塞吗?
- Qt双缓冲行为
- 如何在没有缓冲的情况下使用 parquet-cpp 写入面向流/行的数据?
- MySQL 事务和缓冲的请求列表
- 服务器状态到 XML 使用 fwrite?
- fwrite 4 字符数组,将写入 7 而不是 4
- 使用 std::stringbuf 进行缓冲的效果,同时通过插入运算符'<<'执行写入
- Qt 帧缓冲对象甚至不渲染顶点
- MySQL连接器C 结果集被缓冲
- 了解 fwrite() 的缓冲行为