如何使用boost :: iostreams更改缓冲区大小?

时间:2010-07-08 23:47:49

标签: c++ boost

我的程序并行读取几十个非常大的文件,一次只读一行。似乎主要的性能瓶颈是HDD在文件之间寻找时间(虽然我不完全确定如何验证这一点),所以我认为如果我可以缓冲输入会更快。

我正在使用这样的C ++代码通过boost :: iostreams“过滤流”来读取我的文件:

input = new filtering_istream;
input->push(gzip_decompressor());
file_source in (fname);
input->push(in);

根据documentationfile_source无法设置缓冲区大小,但filtering_stream :: push似乎:

void push( const T& t,
  std::streamsize buffer_size,
  std::streamsize pback_size );

所以我尝试了input->push(in, 1E9),确实我的程序的内存使用量大了,但速度根本没有变化。

读取缓冲是否会改善性能,我是错误的吗?或者我做错了吗?我可以直接缓冲file_source,还是需要创建filtering_streambuf?如果是后者,那怎么办?文档并没有完整的例子。

1 个答案:

答案 0 :(得分:2)

您也应该对其进行分析,看看瓶颈在哪里。

也许它在内核中,也许是你的硬件限制。直到你描述它,发现你在黑暗中磕磕绊绊。

修改

好的,这次是一个更彻底的答案。根据Boost.Iostreams文档basic_file_source只是std::filebuf的包装,而std::streambuf依赖于streambuf。引用文档:

  

以只读模式打开的std :: basic_filebuf的CopyConstructible和Assignable包装器。

#include <fstream> int main() { char buf[4096]; std::ifstream f; f.rdbuf()->pubsetbuf(buf, 4096); f.open("/tmp/large_file", std::ios::binary); while( !f.eof() ) { char rbuf[1024]; f.read(rbuf, 1024); } return 0; } 确实提供了一种方法pubsetbuf(可能不是最好的参考,但是第一个谷歌出现了),你可以用来控制缓冲区大小。

例如:

basic_file_sink

在我的测试中(虽然优化了)但实际上我使用4096字节缓冲区的性能比16字节缓冲区差但是YMMV - 这是为什么你应该总是首先分析它的一个很好的例子:)

但是,正如您所说,filebuf没有提供任何方法来访问它,因为它隐藏了private part中的基础filebuf

如果您认为这是错误的,您可以:

  1. 敦促Boost开发人员公开此类功能,使用邮件列表或trac。
  2. 构建您自己的Total DISK READ: 31.23 M/s | Total DISK WRITE: 109.36 K/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 19502 be/4 staffan 31.23 M/s 0.00 B/s 0.00 % 91.93 % ./apa 包装器,它会公开缓冲区大小。本教程中有一个section解释了编写可能是一个很好的起点的自定义源。
  3. 根据您想要的所有缓存编写自定义源代码。
  4. 请记住,你的硬盘和内核已经对文件读取进行了缓存和缓冲,我认为你不会因为缓存而获得更多的性能提升。

    最后,关于剖析的一个词。 Linux上有很多强大的分析工具,我甚至不知道它们中的一半,但是例如iotop有点整洁,因为它使用起来非常简单。它非常像top,而是显示与磁盘相关的指标。例如:

    {{1}}

    告诉我,我的程序花费了90%以上的时间等待IO,即它的IO绑定。如果您需要更强大的功能,我相信谷歌可以帮助您。

    请记住,在热或冷缓存上进行基准测试会极大地影响结果。