Ruby zlib 库解压 gzip 文件非常慢

Posted

技术标签:

【中文标题】Ruby zlib 库解压 gzip 文件非常慢【英文标题】:Ruby zlib Library Very Slow to Decompress gzip File 【发布时间】:2016-10-14 02:00:35 【问题描述】:

我正在使用 Ruby 的 ZLib 库来解压缩一个很小的 ​​(10k) gzip 文件(在内存中使用 StringIO 类),它需要大约 2.5 秒来解压缩。压缩数据大约需要 100 毫秒,所以我不明白为什么解压缩的时间比压缩函数要长。

我的函数接受一个 StringIO 对象(包含压缩数据的内容)并返回一个由 (3 - 其中 '3' 由 int_size 参数定义的) 字节整数组成的数组,例如:

def decompress(io, int_size = 3)
  array = Array.new(262144)
  i = 0
  io.rewind
  gz = Zlib::GzipReader.new(io)
  until gz.eof?
    buffer = gz.read(int_size)
    array[i] = buffer.unpack('C*').inject  |r, n| r << 8 | n 
    i += 1
  end
  array
end

同一文件在 OSX 命令行中一眨眼就解压缩了。

是否有更快的解压缩文件的方法,或者更快的库或使用本地系统上的 gzip 的方法来实现这一点比现在快得多

【问题讨论】:

尽可能使用系统工具,这些工具的效率惊人。它们经过超级优化且非常可靠。 是的,我就是这么想的——但是我该怎么做呢? blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html 是的,出了点问题。在我四岁的 2 GHz i7 上解压缩 10K 大约需要 150 秒。 【参考方案1】:

我不确定那里发生了什么(我仅使用高度压缩的 gzip 文件重现了缓慢),但一次解压缩更快,如下所示:

def decompress(io, int_size = 3)
    array = Array.new(262144)
    i = 0
    io.rewind
    gz = Zlib::GzipReader.new(io)
    dec = gz.read
    seq = StringIO.new(dec, "rb")
    until seq.eof?
        buffer = seq.read(int_size)
        array[i] = buffer.unpack('C*').inject  |r, n| r << 8 | n 
        i += 1
    end
    array
end

更快的是使用map 而不是循环:

def decompress(io, int_size = 3)
    io.rewind
    gz = Zlib::GzipReader.new(io)
    dec = gz.read
    dec.unpack('C*').each_slice(int_size).to_a.map |t| t.inject |r,n| r << 8 | n
end

【讨论】:

【参考方案2】:

你也可以使用ruby-zstds,它和gzip有类似的api。但是zstd压缩和解压非常快。请尝试。

【讨论】:

以上是关于Ruby zlib 库解压 gzip 文件非常慢的主要内容,如果未能解决你的问题,请参考以下文章

Delphi 使用 ZLib 压缩和解压 GZip

数据流压缩之应用篇zlib库

数据流压缩之应用篇zlib库

在 Ruby 中压缩 Gzip 字符串

协议分析Gzip格式与解析

zabbix准备:nginx安装