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 毫秒