nh2*_*nh2 16 performance hard-drive gzip buffer
我有一些 JSON 文件,每个 20 GB,我想用gzip以下文件进行压缩:
gzip file1.json
Run Code Online (Sandbox Code Playgroud)
这占用了一个完整的 CPU 内核,一切正常。
它处理大约 25 MB/s(签入atop),我的硬盘驱动器可以读取 125 MB/s 并且我有 3 个空闲处理器内核,所以我希望在并行压缩多个文件时获得加速。所以我在其他终端运行:
gzip file2.json
gzip file3.json
gzip file4.json
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,我的吞吐量没有增加;每个核心上的 CPU 大约为 25%,而我的 HD 仍然只能以 25 MB/s 的速度读取。
为什么以及如何解决?
nh2*_*nh2 19
我发现了:
原因是gzip操作(就 CPU 速度与这些天的高清搜索速度而言)极低的缓冲区大小。
它从输入文件中读取几 KB,对其进行压缩,然后将其刷新到输出文件中。鉴于这需要硬盘驱动器寻道,每秒只能完成几个操作。
我的表现没有扩大的原因是因为已经有人gzip在疯狂地寻找。
我通过使用 unixbuffer实用程序解决了这个问题:
buffer -s 100000 -m 10000000 -p 100 < file1.json | gzip > file1.json.gz
Run Code Online (Sandbox Code Playgroud)
通过在将大量输入发送到 gzip 之前对其进行缓冲,可以显着减少小型搜索的数量。选项:
-s并-m指定缓冲区的大小(我相信它以 KB 为单位,但不确定)-p 100 确保数据仅在缓冲区 100% 填充后才传递给 gzip并行运行其中的四个,我可以获得 4 * 25 MB/s 的吞吐量,正如预期的那样。
我仍然想知道为什么 gzip 不允许增加缓冲区大小 - 这样,如果在旋转磁盘上运行它就毫无用处。
编辑:我尝试了更多的压缩程序行为:
bzip2 由于其更强/更多 CPU 密集型压缩,仅处理 2 MB/slzop 似乎允许更大的缓冲区:每个内核 70 MB/s,2 个内核可以在不过度搜索的情况下最大化我的 HD小智 5
在阅读了 MIT OpenCourseware for 6.172 的前五节左右的讲座后:“软件系统的性能工程”,我在一个中等大的测试文件上运行了 Linux 性能分析器“perf”。结果似乎显示流水线停顿,其中一条指令必须等待前一条指令的结果。
? while (lookahead != 0) {
? /* Insert the string window[strstart .. strstart+2] in the
? * dictionary, and set hash_head to the head of the hash chain:
? */
? INSERT_STRING(strstart, hash_head);
2.07 ? movzbl 0x8096d82(%edx),%eax
3.99 ? mov %edx,%ebp
? shl $0x5,%ecx
0.03 ? and $0x7fff,%ebp
1.94 ? xor %ecx,%eax
1.43 ? and $0x7fff,%eax
2.01 ? mov %eax,0x805e588
2.40 ? add $0x8000,%eax
0.88 ? movzwl 0x8062140(%eax,%eax,1),%ecx
23.79 ? movzwl %cx,%edi
? /* Find the longest match, discarding those <= prev_length.
Run Code Online (Sandbox Code Playgroud)
倒数第二条指令正在复制,%ecx最后一条指令必须等待(暂停流水线),直到%cx寄存器准备好使用数据。这个管道停顿阻止了包含循环。
这是一些非常晦涩的“老派”C 编程风格的结果。
| 归档时间: |
|
| 查看次数: |
17366 次 |
| 最近记录: |