【问题标题】:Utilizing multi core for tar+gzip/bzip compression/decompression利用多核进行 tar+gzip/bzip 压缩/解压缩
【发布时间】: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% 的状态。这是最好的解决方案。

标签: gzip tar bzip2 bzip


【解决方案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
    

    【讨论】:

    • 这确实是最好的答案。我一定会重建我的焦油!
    • 我刚刚找到了pbzip2mpibzip2。 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 来实现多线程。
      猜你喜欢
      • 2011-06-14
      • 1970-01-01
      • 2017-05-01
      • 1970-01-01
      • 2012-02-12
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 2015-02-06
      相关资源
      最近更新 更多