酷Go推荐 高性能 gzip 压缩工具 pgzip

bupt_xingxin · 2021年10月18日 · 最后由 bupt_xingxin 回复于 2021年11月11日 · 385 次阅读
本帖已被设为精华帖!

背景

gzip 是当前应用非常广泛的文件压缩格式,golang 中也有内置的 compress/gzip 对其提供原生支持。今天我们要介绍的 pgzip 是一款完全兼容 gzip 的插件,并能提供相较于 compress/gzip 上百倍的性能提升!

pgzip 简介

pgzip(https://github.com/klauspost/pgzip) 主要是通过分块并行压缩实现性能提升的,尤其适用于大量数据(>1MB)压缩的场景。由于 pgzip 的 API 设计完全兼容 compress/gzip,因此我们的工程升级到 pgzip 只需要特别小的改动:

import gzip "github.com/klauspost/pgzip"

另外,pgzip 还支持指定并发度,我们可以据此对压缩消耗的 CPU 资源进行管控;pgzip 还附带了一个线性时间压缩模式(Huffman only compression),该模式支持以每核每秒约 250MB 的速度进行数据压缩。

应用举例

随机生成一个 100MB 的大文件作为待压缩文件:

dd if=/dev/random of=data.bin bs=4m count=25

首先使用原生的 compress/gzip 进行压缩:

package main

import (
    "compress/gzip"
    "io"
    "log"
    "os"
)

func main() {
    fr, err := os.Open("data.bin")
    if err != nil {
        log.Fatalf("failed to open file to read: %v", err)
    }
    defer fr.Close()

    fw, err := os.Create("gzip_res.gz")
    if err != nil {
        log.Fatalf("failed to open file to write: %v", err)
    }
    defer fw.Close()

    w := gzip.NewWriter(fw)
    defer w.Close()
    _, err = io.Copy(w, fr)
    if err != nil {
        log.Fatalf("failed to gzip: %v", err)
    }
}

查看执行时间:

$ go build -o gzip_demo
$ time ./gzip_demo
./gzip_demo  1.86s user 0.23s system 99% cpu 2.111 total

现在我们切换到 pgzip 对同样的文件进行压缩:

package main

import (
    "io"
    "log"
    "os"

    gzip "github.com/klauspost/pgzip"
)

func main() {
    fr, err := os.Open("data.bin")
    if err != nil {
        log.Fatalf("failed to open file to read: %v", err)
    }
    defer fr.Close()

    fw, err := os.Create("pgzip_res.gz")
    if err != nil {
        log.Fatalf("failed to open file to write: %v", err)
    }
    defer fw.Close()

    w := gzip.NewWriter(fw)
    defer w.Close()
    // 1MB block with 4 concurrency
    w.SetConcurrency(1<<20, 4)
    _, err = io.Copy(w, fr)
    if err != nil {
        log.Fatalf("faield to gzip: %v", err)
    }
}

查看执行时间:

$ go build -o pgzip_demo
$ time ./pgzip_demo
./pgzip_demo  0.07s user 0.08s system 240% cpu 0.064 total

可见,使用 pgzip 压缩同样 100MB 大小的文件,使用 4 核 CPU 时压缩耗时有几十倍(1.86s -> 0.07s)的缩短!

总结

pgzip 实现了分块并行的 gzip 压缩能力,极大提升了压缩速率,能够充分利用多核 CPU 的计算资源。当然,pgzip 提升压缩速率的同时也会消耗更多的计算资源,能够达到的压缩比也会比原生 gzip 略低。

pgzip 非常适用于大文件压缩的场景,例如提升构建产物的打包速率、优化数据备份时效等,快来试试吧!

参考资料


欢迎加入 GOLANG 中国社区:https://gocn.vip

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
kevin 将本帖设为了精华贴 10月19日 10:57

我想知道的是,这个是用法兼容,还是说压缩之后的文件也兼容,看到说是分块并行压缩,感觉可能是一个个的文件块分别压缩了之后合并,这样的话,每个块都是一个完整的 gzip 的包,然后合体?感觉如果是这样的话,估计是不兼容原生文件格式了

suiyunonghen 回复

当然是压缩后的文件也会兼容。pgzip 可以片面的理解成以压缩率损失换来了性能提升,但是都会 follow gzip 的协议

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册