gzip 与 lz4 压缩对比

gzip

使用 gzip 减少内存使用率

import 	"compress/gzip"

// Gzip 压缩
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
}

// UnGzip 解压
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
}

压缩率-测试

// gzip 测试
func Test_gzip(t *testing.T) {
	// 定义一个40MB的字符串
	originalStr := generateTestData(1024 * 1024 * 40)

	gzipByte, err := Gzip([]byte(originalStr))
	if err != nil {
		return
	}

	t.Log("originalStr", len([]byte(originalStr))) // originalStr 41943040
	t.Log("gzipByte", len(gzipByte)) // gzipByte 163033

	unGzip, err := UnGzip(gzipByte)
	if err != nil {
		t.Logf("unGzip err:%v", err)
		return
	}

	t.Log("unGzip", len(unGzip)) // unGzip 41943040
	t.Log("压缩比例", float64(len(gzipByte))/float64(len(originalStr))) // 压缩比例 0.0038870096206665037
}

func generateTestData(size int) []byte {
	data := make([]byte, size)
	for i := 0; i < size; i++ {
		data[i] = byte(i % 256)
	}
	return data
}
    string_test.go:81: originalStr 41943040
    string_test.go:82: gzipByte 163033
    string_test.go:90: unGzip 41943040

性能测试

func generateTestData(size int) []byte {
	data := make([]byte, size)
	for i := 0; i < size; i++ {
		data[i] = byte(i % 256)
	}
	return data
}

func BenchmarkGzip(b *testing.B) {
	data := generateTestData(1024 * 1024 * 40) // 40MB test data
	b.ResetTimer()
  // 测试次数设置为 1000 次
  b.N = 1000
	for i := 0; i < b.N; i++ {
		Gzip(data)
	}
}

func BenchmarkUnGzip(b *testing.B) {
	data := generateTestData(1024 * 1024 * 40) // 40MB test data
	gzippedData, _ := Gzip(data)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		UnGzip(gzippedData)
	}
}
BenchmarkGzip
BenchmarkGzip-8   	    1000	  86227659 ns/op
平均每次迭代执行耗时约 86.2 毫秒

BenchmarkUnGzip
BenchmarkUnGzip-8   	    1000	  22937552 ns/op
每次迭代执行耗时约 22.9 毫秒

LZ4

// LZ4 压缩
func LZ4(data []byte, buffSize int) ([]byte, error) {
	buf := make([]byte, buffSize)
	var c lz4.Compressor
	n, err := c.CompressBlock(data, buf)
	if err != nil {
		return nil, err
	}
	if n >= len(data) {
		return nil, errors.New("compress failed")
	}
	return buf[:n], nil
}

// UnLZ4 解压
func UnLZ4(data []byte, buffSize int) ([]byte, error) {
	out := make([]byte, buffSize)
	n, err := lz4.UncompressBlock(data, out)
	if err != nil {
		return nil, err
	}
	return out[:n], nil
}

压缩率-测试

// lz4 测试
func Test_lz4(t *testing.T) {
	// 定义一个40MB的字符串
	originalStr := generateTestData(1024 * 1024 * 40)

	// lz4 压缩
	buffSize := lz4.CompressBlockBound(len(originalStr))

	t.Log("buffSize", buffSize) // buffSize 42107538

	lz4Byte, err := LZ4(originalStr, buffSize)
	if err != nil {
		return
	}

	t.Log("originalStr", len(originalStr)) // originalStr 41943040
	t.Log("lz4Byte", len(lz4Byte)) // lz4Byte 164760

	// lz4 解压
	unLz4, err := UnLZ4(lz4Byte, buffSize)
	if err != nil {
		t.Logf("unLz4 err:%v", err)
		return
	}
	t.Log("unLz4", len(unLz4)) // unLz4 41943040

	t.Log("压缩比例", float64(len(lz4Byte))/float64(len(originalStr))) // 压缩比例 0.003928184509277344
}

func generateTestData(size int) []byte {
	data := make([]byte, size)
	for i := 0; i < size; i++ {
		data[i] = byte(i % 256)
	}
	return data
}

性能测试

func BenchmarkLZ4(b *testing.B) {
	data := generateTestData(1024 * 1024 * 40) // 40MB test data
	buffSize := lz4.CompressBlockBound(len(data))

	// 测试 1000 次
	b.N = 1000
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		LZ4(data, buffSize)
	}
}

func BenchmarkUnLZ4(b *testing.B) {
	data := generateTestData(1024 * 1024 * 40) // 40MB test data
	buffSize := lz4.CompressBlockBound(len(data))

	gzippedData, _ := LZ4(data, buffSize)
	// 测试 1000 次
	b.N = 1000
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		UnLZ4(gzippedData, buffSize)
	}
}
BenchmarkLZ4
BenchmarkLZ4-8   	    1000	   7001739 ns/op
平均每次迭代执行耗时约 7.00 毫秒

BenchmarkUnLZ4
BenchmarkUnLZ4-8   	    1000	   2472194 ns/op
平均每次迭代执行耗时约 2.47 毫秒

Gzip vs LZ4

压缩效率

Gzip 在压缩同等大小的字符(40MB)时,压缩率略高于 LZ4:

  • Gzip 压缩后大小为:163033

  • LZ4 压缩后大小为:164760

压缩时长

Gzip 在压缩同等大小字符时远远大于 LZ4:

  • Gzip 压缩时长:平均每次迭代执行耗时约 86.2 毫秒
  • Gzip 解压时长:每次迭代执行耗时约 22.9 毫秒
  • LZ4 压缩时长:平均每次迭代执行耗时约 7.00 毫秒
  • LZ4 解压时长:平均每次迭代执行耗时约 2.47 毫秒

你可能感兴趣的:(golang)