我正在使用pythons bz2模块生成(并压缩)一个大的jsonl文件(bzip2压缩17GB)。
但是,当我后来尝试使用 pbzip2 解压它时,它似乎只使用 one CPU 核心来解压,这非常慢。
当我用 pbzip2 压缩它时,它可以利用多个核心进行解压缩。有没有办法在 python 中以 pbzip2 兼容格式进行压缩?
import bz2,sys
from Queue import Empty
#...
compressor = bz2.BZ2Compressor(9)
f = open(path, 'a')
try:
while 1:
m = queue.get(True, 1*60)
f.write(compressor.compress(m+"\n"))
except Empty, e:
pass
except Exception as e:
traceback.print_exc()
finally:
sys.stderr.write("flushing")
f.write(compressor.flush())
f.close()
一个
pbzip2
流只不过是多个 bzip2
流的串联。
使用 shell 的示例:
bzip2 < /usr/share/dict/words > words_x_1.bz2
cat words_x_1.bz2{,,,,,,,,,} > words_x_10.bz2
time bzip2 -d < words_x_10.bz2 > /dev/null
time pbzip2 -d < words_x_10.bz2 > /dev/null
我从未使用过 python 的
bz2
模块,但应该很容易在 'a'
pend 模式下关闭/重新打开流,每这么多字节,以获得相同的结果。请注意,如果 BZ2File
是从现有的类文件对象构造的,则关闭 BZ2File
将不会关闭底层流(这正是您想要的)。
我还没有测量多少字节最适合分块,但我猜测每 1-20 MB - 它肯定需要大于 bzip2 块大小 (900k)。
另请注意,如果记录每个块的压缩和未压缩偏移量,则可以进行相当有效的随机访问。这就是
dictzip
程序的工作方式,尽管它是基于 gzip
。
如果您绝对必须在解压时使用
pbzip2
,这对您没有帮助,但替代方案 lbzip2
可以对“正常”.bz2
文件执行多核解压,例如由 Python 的 BZ2File
或传统 生成的文件bzip2
命令。这避免了您所描述的 pbzip2
的限制,即只有使用 pbzip2
压缩文件时才能实现并行解压缩。请参阅https://github.com/kjn/lbzip2/。
作为奖励,基准测试表明
lbzip2
比 pbzip2
快得多,无论是解压(快 30%)还是压缩(快 40%),同时实现略优的压缩比。此外,其峰值 RAM 使用量还不到 pbzip2
使用的 RAM 的 50%。请参阅https://vbtechsupport.com/1614/。