gnu gzip 解压明显慢于 zlib

问题描述 投票:0回答:1

GNU gzip 和 zlib 由同一作者编写。然而,我注意到两者的解压速度差异很大。

例如,使用 gnu gzip 解压

linux.tar.gz
需要 4.5 秒,而 zlib 在我的电脑上只需要 2.6 秒。当我对两者进行分析时,我注意到与 zlib 相比,GNU gzip 在 crc32 计算上花费的时间明显更多。

using zlib under the hood
Overhead  Command  Shared Object     Symbol
  58.41%  gunzip   gunzip            [.] inflate_fast
  12.60%  gunzip   gunzip            [.] crc32_z
   2.57%  gunzip   [unknown]         [k] 0xffffffff94c247e7
   1.82%  gunzip   gunzip            [.] inflate
   1.42%  gunzip   libc.so.6         [.] __memmove_avx_unaligned_erms
   1.19%  gunzip   [unknown]         [k] 0xffffffff94c250ba
   0.81%  gunzip   [unknown]         [k] 0xffffffff94c28ec9
gnu gzip
Overhead  Command  Shared Object     Symbol
  62.78%  gzip     gzip              [.] flush_window                                                                                                                
  19.47%  gzip     gzip              [.] inflate_codes                                                                                                               
   4.32%  gzip     libc.so.6         [.] __memmove_avx_unaligned_erms                                                                                                
   1.40%  gzip     [unknown]         [k] 0xffffffff94c247e7                                                                                                          
   0.60%  gzip     [unknown]         [k] 0xffffffff94c250ba         

这似乎表明 gnu gzip 上的 crc32 计算效率不如 zlib。查看代码,gnu gzip 确实依赖于基于 crc32 的简单表查找,而 zlib 似乎使用了更加优化/复杂的实现。

如果确实如此,我想知道为什么他们不能共享相同的 crc32 计算,从而也加快 gnu gzip 的速度。鉴于几乎所有 Linux 发行版都附带了 gnu gzip,因此将其性能提高到与 zlib 相当将非常有益。

如果不是,我很好奇为什么两者的性能差异如此之大。

-- 编辑 --

我没有提到

flush_window()
大部分时间都在
updcrc()

Percent│      test    %ebp,%ebp                                                                                                                                      
       │      je      78                                                                                                                                             
       │    updcrc():                                                                                                                                                
       │    c = crc;                                                                                                                                                 
       │      mov     %ebp,%r8d                                                                                                                                      
       │      lea     window,%rdx                                                                                                                                    
       │      mov     crc,%rax                                                                                                                                       
       │    if (n) do {                                                                                                                                              
  0.01 │      lea     crc_32_tab,%rsi                                                                                                                                
       │      lea     (%rdx,%r8,1),%rdi                                                                                                                              
       │      xchg    %ax,%ax                                                                                                                                        
       │    c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);                                                                                                     
 10.37 │30:   movzbl  (%rdx),%ecx                                                                                                                                    
 10.55 │      add     $0x1,%rdx                                                                                                                                      
 17.32 │      xor     %eax,%ecx                                                                                                                                      
 18.65 │      shr     $0x8,%rax                                                                                                                                      
 12.89 │      movzbl  %cl,%ecx                                                                                                                                       
 19.73 │      xor     (%rsi,%rcx,8),%rax                                                                                                                             
       │    } while (--n);                                                                                                                                           
 10.45 │      cmp     %rdi,%rdx                                                                                                                                      
       │      jne     30                                                                                                                                             
       │    crc = c;                                                                                                                                                 
  0.02 │      mov     %rax,crc                          

下面是来自 GNU gzip 的火焰图

下面是 zlib 周围薄包装的火焰图

在运行 Ubuntu 22.04 的 AMD 7735HS 系统上进行测试,使用 -O3 编译。

gzip zlib crc32
1个回答
0
投票

这确实是由于crc32计算造成的。

参考: https://lists.gnu.org/r/bug-gzip/2023-11/msg00000.html

© www.soinside.com 2019 - 2024. All rights reserved.