C BZ2_bzDecompress方式比bzip2命令慢
Posted
技术标签:
【中文标题】C BZ2_bzDecompress方式比bzip2命令慢【英文标题】:C BZ2_bzDecompress way slower than bzip2 command 【发布时间】: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 的最新版本@,失败了,在我有机会测试它之前,我将不再发表评论。
【参考方案1】:
交换,mmap 标志与他们无关。如果 bzip2 慢,那不是文件 I/O 的原因。
我认为您的 libbz2 没有完全优化。用你能想象到的最残酷的 gcc 标志重新编译它。
我的第二个想法是是否存在一些 ELF 链接开销。在这种情况下,如果您静态链接 bz2,问题将消失。 (之后您将能够考虑如何使用动态加载的 libbz2 快速完成此操作)。
未来的重要扩展: Libbz2 必须是可重入的、线程安全的和位置无关的。这意味着要使用各种 C 标志进行编译,这些标志对性能没有很好的影响(尽管它们产生的代码要快得多)。在极端情况下,与单线程、非 PIC、不可重入版本相比,我什至可以想象慢 5 到 10 倍。
【讨论】:
以上是关于C BZ2_bzDecompress方式比bzip2命令慢的主要内容,如果未能解决你的问题,请参考以下文章