利用多核进行 tar+gzip/bzip 压缩/解压缩

Posted

技术标签:

【中文标题】利用多核进行 tar+gzip/bzip 压缩/解压缩【英文标题】:Utilizing multi core for tar+gzip/bzip compression/decompression 【发布时间】:2012-09-01 01:12:22 【问题描述】:

我通常使用tar zcvf 压缩并使用tar zxvf 解压缩(由于习惯使用gzip)。

我最近获得了一个具有超线程的四核 CPU,因此我有 8 个逻辑核心,我注意到许多核心在压缩/解压缩期间未使用。

有什么方法可以利用未使用的内核使其更快?

【问题讨论】:

熊嘉米夫上面提出的解决方案效果很好。我刚刚用 .tar.bz2 备份了我的笔记本电脑,只使用一个 cpu 线程就花了 132 分钟。然后我从源代码编译并安装了 tar:gnu.org/software/tar 我包含了配置步骤中提到的选项:./configure --with-gzip=pigz --with-bzip2=lbzip2 --with-lzip=plzip 我运行了备份再次,只用了 32 分钟。这比 4 倍的改进要好!我观察了系统监视器,它使所有 4 个 CPU(8 个线程)始终保持在 100% 的状态。这是最好的解决方案。 【参考方案1】:

您可能要考虑的一个相对较新的(解)压缩工具是zstandard。它在利用备用内核方面做得非常出色,并且在压缩比与(去)压缩时间方面做了一些很好的权衡。它还可以根据您的压缩比需求进行高度调整。

【讨论】:

【参考方案2】:

常用方法

tar 程序有选项:

-I, --use-compress-program PROG
      filter through PROG (must accept -d)

您可以使用多线程版本的归档器或压缩器实用程序。

最流行的多线程存档器是pigz(而不是 gzip)和pbzip2(而不是 bzip2)。例如:

$ tar -I pbzip2 -cf OUTPUT_FILE.tar.bz2 paths_to_archive
$ tar --use-compress-program=pigz -cf OUTPUT_FILE.tar.gz paths_to_archive

归档器必须接受 -d。如果您的替换实用程序没有此参数和/或您需要指定其他参数,则使用管道(必要时添加参数):

$ tar cf - paths_to_archive | pbzip2 > OUTPUT_FILE.tar.gz
$ tar cf - paths_to_archive | pigz > OUTPUT_FILE.tar.gz

单线程和多线程的输入输出兼容。您可以使用多线程版本进行压缩,使用单线程版本进行解压,反之亦然。

p7zip

对于用于压缩的 p7zip,您需要如下所示的小型 shell 脚本:

#!/bin/sh
case $1 in
  -d) 7za -txz -si -so e;;
   *) 7za -txz -si -so a .;;
esac 2>/dev/null

另存为 7zhelper.sh。这里是使用示例:

$ tar -I 7zhelper.sh -cf OUTPUT_FILE.tar.7z paths_to_archive
$ tar -I 7zhelper.sh -xf OUTPUT_FILE.tar.7z

xz

关于多线程 XZ 支持。如果您运行的是 XZ Utils 5.2.0 或更高版本,您可以通过环境变量 XZ_DEFAULTS(例如 XZ_DEFAULTS="-T 0")将 -T--threads 设置为适当的值来利用多个内核进行压缩。

这是 5.1.0alpha 版本的 man 片段:

多线程压缩和解压还没有实现,所以这个 选项暂时无效。

但是,这不适用于解压缩尚未解压的文件 在启用线程的情况下进行压缩。来自 5.2.2 版的 man:

尚未实现线程解压。它只会工作 在包含多个具有大小信息的块的文件上 块头。多线程模式下压缩的所有文件都满足这个 条件,但以单线程模式压缩的文件即使 使用 --block-size=size。

用替换重新编译

如果你从源代码构建 tar,那么你可以使用参数重新编译

--with-gzip=pigz
--with-bzip2=lbzip2
--with-lzip=plzip

使用这些选项重新编译 tar 后,您可以查看 tar 帮助的输出:

$ tar --help | grep "lbzip2\|plzip\|pigz"
  -j, --bzip2                filter the archive through lbzip2
      --lzip                 filter the archive through plzip
  -z, --gzip, --gunzip, --ungzip   filter the archive through pigz

【讨论】:

这确实是最好的答案。我一定会重建我的焦油! 我刚刚找到了pbzip2 和mpibzip2。 mpibzip2 看起来非常适合集群,或者如果您有一台笔记本电脑和一台多核台式机。 这是一个伟大而详尽的答案。值得一提的是,多线程压缩(例如使用pigz)仅在从文件中读取时才启用。处理 STDIN 实际上可能更慢。 xz 选项加 1。这是最简单但有效的方法。 export XZ_DEFAULTS="-T 0" 在调用 tar 之前使用选项 -J 进行 xz 压缩就像一个魅力。【参考方案3】:

如果您希望文件名和压缩选项更灵活,您可以使用:

find /my/path/ -type f -name "*.sql" -o -name "*.log" -exec \
tar -P --transform='s@/my/path/@@g' -cf -  + | \
pigz -9 -p 4 > myarchive.tar.gz

第一步:find

find /my/path/ -type f -name "*.sql" -o -name "*.log" -exec

此命令将查找您要归档的文件,在本例中为 /my/path/*.sql/my/path/*.log。添加任意数量的-o -name "pattern"

-exec 将使用find 的结果执行下一条命令:tar

第二步:tar

tar -P --transform='s@/my/path/@@g' -cf - +

--transform 是一个简单的字符串替换参数。它将从存档中删除文件的路径,以便在解压缩时将 tarball 的根目录变为当前目录。请注意,您不能使用-C 选项来更改目录,因为您将失去find 的好处:将包含目录的所有文件。

-P 告诉tar 使用绝对路径,因此它不会触发警告“Removingleading `/' from member names”。前导 '/' 无论如何都会被 --transform 删除。

-cf - 告诉tar 使用我们稍后会指定的压缩包名称

+ 使用 find 之前找到的所有文件

第三步:pigz

pigz -9 -p 4

使用尽可能多的参数。 在这种情况下,-9 是压缩级别,-p 4 是专用于压缩的核心数。 如果你在负载很重的网络服务器上运行它,你可能不想使用所有可用的内核。

第 4 步:存档名称

> myarchive.tar.gz

终于。

【讨论】:

【参考方案4】:

您可以使用快捷方式 -I 来切换 tar 的 --use-compress-program 开关,并调用 pbzip2 来在多核上进行 bzip2 压缩:

tar -I pbzip2 -cf OUTPUT_FILE.tar.bz2 DIRECTORY_TO_COMPRESS/

【讨论】:

一个不错的 TL;@MaximSuslov 的 answer 的 DR。 返回tar: home/cc/ziptest: Cannot stat: No such file or directory tar: Exiting with failure status due to previous errors`【参考方案5】:

您可以使用pigz 代替 gzip,后者在多个内核上进行 gzip 压缩。您可以通过 pigz 管道而不是使用 -z 选项:

tar cf - paths-to-archive | pigz > archive.tar.gz

默认情况下,pigz 使用可用内核的数量,如果无法查询,则使用 8 个。您可以使用 -p n 询问更多信息,例如-p 32. pigz 具有与 gzip 相同的选项,因此您可以使用 -9 请求更好的压缩。例如

tar cf - paths-to-archive | pigz -9 -p 32 > archive.tar.gz

【讨论】:

如何使用 pigz 以同样的方式解压?还是只适用于压缩? pigz 确实使用多核进行解压,但对单核的改进有限。 deflate 格式不适合并行解压缩。解压部分必须连续进行。 pigz 解压的其他核用于读取、写入和计算 CRC。另一方面,当压缩时,pigz 接近 n 个核心的 n 改进因子。 这里的连字符是stdout(见this page)。 是的。双向 100% 兼容。 实际上没有 CPU 时间花费在 tarring 上,所以它没有多大帮助。 tar 格式只是输入文件的副本,文件之间有头块。【参考方案6】:

您还可以使用 tar 标志“--use-compress-program=”来告诉 tar 使用什么压缩程序。

例如使用:

tar -c --use-compress-program=pigz -f tar.file dir_to_zip 

【讨论】:

这是一个很棒的小知识点,值得更多的支持。我什至不知道这个选项存在,这些年来我已经阅读了几次手册页。 @Valerioschiavoni:不在这里,我在所有 4 个内核上都满负荷运行(Ubuntu 15.04 'Vivid')。 我更喜欢tar - dir_to_zip | pv | pigz > tar.file pv 帮我估计,你可以跳过。但仍然更容易书写和记忆。 @NathanS.Watson-Haigh 是的。只需将程序名称和参数括在引号中即可。 man tar 这么说,this 也是这么说的。 2020 年,zstd 是最快的工具。压缩和解压缩时显着加速。使用tar -cf --use-compress-program=zstdmt 来实现多线程。

以上是关于利用多核进行 tar+gzip/bzip 压缩/解压缩的主要内容,如果未能解决你的问题,请参考以下文章

说说 Linux 中的压缩与解压缩指令(tar)

压缩命令解压缩命令

tar打包和压缩并用

Linux 基础教程 32-解压缩命令

打包压缩命令

打包压缩命令