【发布时间】:2013-09-11 13:03:28
【问题描述】:
我正在使用 mmap/read + BZ2_bzDecompress 顺序解压缩一个大文件 (29GB)。这样做是因为我需要解析未压缩的 xml 数据,但只需要它的一小部分,而且似乎顺序执行此操作比解压缩整个文件(400GB 未压缩)然后解析它更有效。有趣的是,解压部分已经非常慢了——虽然 shell 命令 bzip2 每秒能够执行超过 52MB 的速度(使用了多次运行 timeout 10 bzip2 -c -k -d input.bz2 > output 并将生成的文件大小除以 10),但我的程序甚至不能达到 2MB /s,几秒钟后减慢到 1.2MB/s
我正在尝试处理的文件使用多个 bz2 流,因此我正在检查 BZ2_bzDecompress 中的 BZ_STREAM_END,如果出现这种情况,请使用 BZ2_bzDecompressEnd( strm ); 和 BZ2_bzDecompressInit( strm, 0, 0 ) 重新启动下一个流,在如果文件尚未完全处理。我也尝试不使用BZ2_bzDecompressEnd,但这并没有改变任何东西(而且我在文档中看不到如何正确处理多个流)
该文件之前是 mmap 的,我也尝试了不同的标志组合,目前 MAP_RDONLY、MAP_PRIVATE 与 madvise 到 MADV_SEQUENTIAL | MADV_WILLNEED | MADV_HUGEPAGE(我正在检查返回值,而 madvise 没有报告任何问题,并且我正在使用具有大页面支持的 linux 内核 3.2x debian 设置)
在进行分析时,我确保除了一些用于测量速度的计数器和一个限制为每 n 次迭代一次的 printf 之外,没有运行其他任何东西。这也是在现代多核服务器处理器上,所有其他内核都处于空闲状态,并且是裸机,未虚拟化。
关于我可能做错什么/做些什么来提高性能有什么想法吗?
更新:感谢James Chong 的建议,我尝试将mmap() 与read()“交换”,速度还是一样。所以看起来mmap() 不是问题(或者mmap() 和read() 共享一个潜在的问题)
更新 2:考虑到在 bzDecompressInit/bzDecompressEnd 中完成的 malloc/free 调用可能是原因,我将 bz_stream 结构的 bzalloc/bzfree 设置为一个自定义实现,它只在第一次分配内存并且不释放它,除非设置了一个标志(由 opaque 参数 = strm.opaque 传递)。它工作得很好,但速度再次没有增加。
更新 3:我现在也尝试了 fread() 而不是 read(),但速度仍然保持不变。还尝试了不同数量的读取字节和解压缩数据缓冲区大小 - 没有变化。
更新 4:读取速度绝对不是问题,因为我已经能够在仅使用 mmap() 的顺序读取中实现接近 120MB/s 的速度。
【问题讨论】:
-
我会尝试“手动”读取文件(即
read()),看看mmap是否有任何问题。也可能是您正在链接 bz2 库的调试版本? -
@JamesChong 我将尝试 read() 方法并报告 - 我正在使用 debian 提供的软件包 libbz2(+ libbz2-dev 用于头文件),所以它不应该是调试版本 - 或者至少,应该与 bzip2 命令使用的版本相同,所以应该不是问题。
-
@JamesChong 经过大量工作后,我使用 read() 完成了整个工作(因为我不必使用 mmap 处理剩余的数据偏移量,read() 代码稍微复杂一些),但是使用 read() 时没有性能差异。
-
神秘 :( 不幸的是,我还没有时间为自己对 bz2 库进行基准测试。如果我可以提供最后一个建议:尝试编译并静态链接来自 @987654337 的最新版本@,失败了,在我有机会测试它之前,我将不再发表评论。
标签: c performance bzip2