参考美团技术博客 压缩算法在构建部署中的优化
源码:
package utils
import (
"bytes"
"compress/gzip"
"errors"
"github.com/pierrec/lz4/v4"
"io/ioutil"
)
func LZ4(data []byte) ([]byte, error) {
buf := make([]byte, lz4.CompressBlockBound(len(data)))
var c lz4.Compressor
n, err := c.CompressBlock(data, buf)
if err != nil {
return nil, err
}
if n >= len(data) {
return nil, errors.New("not compressible")
}
return buf[:n], nil
}
func UnLZ4(data []byte) ([]byte, error) {
// Allocate a very large buffer for decompression.
out := make([]byte, 10*len(data))
n, err := lz4.UncompressBlock(data, out)
if err != nil {
return nil, err
}
return out[:n], nil
}
func Gzip(data []byte) ([]byte, error) {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
_, err := w.Write(data)
if err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func UnGzip(data []byte) ([]byte, error) {
buf := bytes.NewBuffer(data)
r, err := gzip.NewReader(buf)
if err != nil {
return nil, err
}
result, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
if err := r.Close(); err != nil {
return nil, err
}
return result, nil
}
压测源码
package utils
import (
"io/ioutil"
"os"
"testing"
)
func prepareData() []byte {
// Compress and uncompress an input string.
f, err := os.Open("{your_file_path}")
if err != nil {
panic(err)
}
data, err := ioutil.ReadAll(f)
if err != nil {
panic(err)
}
return data
}
func BenchmarkLZ4(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
data := prepareData()
for pb.Next() {
_, err := LZ4(data)
if err != nil {
panic(err)
}
}
})
}
func BenchmarkUnLZ4(b *testing.B) {
data := prepareData()
encoded, err := LZ4(data)
if err != nil {
panic(err)
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := UnLZ4(encoded)
if err != nil {
panic(err)
}
}
})
}
func BenchmarkGzip(b *testing.B) {
data := prepareData()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := Gzip(data)
if err != nil {
panic(err)
}
}
})
}
func BenchmarkUnGzip(b *testing.B) {
data := prepareData()
encoded, err := Gzip(data)
if err != nil {
panic(err)
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := UnGzip(encoded)
if err != nil {
panic(err)
}
}
})
}
测试一下压缩速度(压缩比可以参考上面贴的文章,gzip/lz4 压缩比差距不大,这里主要对比速度):
gzip
- 优点: 相对通用
- 缺点:较慢
lz4
- 优点:压缩/解压 速度非常快,大约是 gzip 10 倍
- 缺点:相对 gzip, 通用性稍低