golang常用库之- pierrec/lz4包 | lz4命令、lz4压缩算法(高压解速度)

golang常用库之-golang常用库之- pierrec/lz4包 | lz4压缩算法(高压解速度)

LZ4压缩算法

官网: https://lz4.github.io/lz4/

Yann Collet 在2011年发明了LZ4压缩算法。

LZ4 是无损压缩算法,提供每核 > 500 MB/s (>0.15 Bytes/cycle) 的压缩速度。它具有速度极快的解码器,每个内核的速度为数 GB/s(~1 字节/周期)。一种称为 LZ4_HC 的高压缩衍生产品可用,它以可定制的 CPU 时间换取压缩比。LZ4 库是使用 BSD 许可证作为开源软件提供的。

lz4
优点:压缩/解压 速度非常快,大约是 gzip 10 倍。 lz4保证一定压缩率的情况下,它以无敌的压缩速度和更快的解压速度著称
缺点:相对 gzip, 通用性稍低

总结: lz4是目前综合来看效率最高的压缩算法,更加侧重压缩解压速度,压缩比并不是第一。

lz4官网提供了个语言操作lz4的链接,其中go填写的 Go Pierre Curto https://github.com/pierrec/lz4 仓库。

lz4使用场景

lz4是一个让"人见人爱、花见花开"的压缩算法,能够在多核上很好的扩展。lz4在压缩率上略微逊色, 但是在解压速度上有着惊人的优势 (大概是gzip的3倍(多次测试对比))。因为压缩时高效的多核利用,再加上惊艳的解压,lz4已经在非常多重要场合使用了! 对于需要频繁压缩、实时快速解压的场景来说,lz4非常适合;lz4 解压缩的对象是文件而不是目录。

lz4命令工具安装和使用

yum install -y lz4 lz4-devel 
压缩 (默认解压之后的名称filename.lz4)
# lz4 filename       

解压缩
# lz4 -d filename.lz4

centos7下默认有lz4_decompress 命令,可以直接解压, 并可以定义解压后的文件名
# lz4_decompress filename.lz4 filename
# lz4_decompress filename.lz4 filename.txt

lz4参数解释

 lz4 --help

参数
-1:  快速压缩(默认)
-9:  高压缩
-d:  解压缩(默认为.lz4扩展名)
-z:  强制压缩
-f:  覆盖输出而不提示
-k:  保留源文件(默认)
--rm:  成功地解除/压缩后删除源文件
-h/-h:  显示帮助/长帮助和退出

高级参数
-v:  显示版本号并退出
-v:  详细模式
-q:  取消警告;指定两次也可以取消错误
-c:  强制写入标准输出,即使它是控制台
-t:  测试压缩文件完整性
-m:  多个输入文件(表示自动输出文件名)
-r:  在目录上递归操作(也设置为-m)
-l:  使用旧格式压缩(Linux内核压缩)

pierrec/lz4包

github: https://github.com/pierrec/lz4/

This package provides a streaming interface to LZ4 data streams as well as low level compress and uncompress functions for LZ4 data blocks. The implementation is based on the reference C one.
此软件包提供LZ4数据流的流接口,以及LZ4的数据块的底层压缩和解压缩功能。该实现基于参考C。

代码demo

官方demo:读取字节码中解压

package lz4_test

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/pierrec/lz4/v4"
)

func Example() {
    
    
	// Compress and uncompress an input string.
	s := "hello world"
	r := strings.NewReader(s)

	// The pipe will uncompress the data from the writer.
	pr, pw := io.Pipe()
	zw := lz4.NewWriter(pw)
	zr := lz4.NewReader(pr)

	go func() {
    
    
		// Compress the input string.
		_, _ = io.Copy(zw, r)
		_ = zw.Close() // Make sure the writer is closed
		_ = pw.Close() // Terminate the pipe
	}()

	_, _ = io.Copy(os.Stdout, zr)

	// Output:
	// hello world
}

func ExampleCompressBlock() {
    
    
	s := "hello world"
	data := []byte(strings.Repeat(s, 100))
	buf := make([]byte, lz4.CompressBlockBound(len(data)))

	var c lz4.Compressor
	n, err := c.CompressBlock(data, buf)
	if err != nil {
    
    
		fmt.Println(err)
	}
	if n >= len(data) {
    
    
		fmt.Printf("`%s` is not compressible", s)
	}
	buf = buf[:n] // compressed data

	// Allocate a very large buffer for decompression.
	out := make([]byte, 10*len(data))
	n, err = lz4.UncompressBlock(buf, out)
	if err != nil {
    
    
		fmt.Println(err)
	}
	out = out[:n] // uncompressed data

	fmt.Println(string(out[:len(s)]))

	// Output:
	// hello world
}

总结: golang解压lz4压缩的字节,核心就是利用 官方 UncompressBlock函数。

UncompressBlock将源缓冲区解压缩到目标缓冲区,并返回未压缩的大小。目标缓冲区的大小必须适当。如果源数据无效或目标缓冲区太小,则返回错误。
利用字节数据不是lz4压缩的数据,你解压就好报错: lz4errors.Error=lz4: invalid source or destination buffer too short

// UncompressBlock uncompresses the source buffer into the destination one,
// and returns the uncompressed size.
//
// The destination buffer must be sized appropriately.
//
// An error is returned if the source data is invalid or the destination buffer is too small.
func UncompressBlock(src, dst []byte) (int, error) {
    
    
	return lz4block.UncompressBlock(src, dst, nil)
}

参考

速度与压缩比如何兼得?压缩算法在构建部署中的优化
参考URL: https://tech.meituan.com/2021/01/07/pack-gzip-zstd-lz4.html
速度之王 — LZ4压缩算法(一)
参考URL: https://www.cnblogs.com/aiwz/p/6333317.html

猜你喜欢

转载自blog.csdn.net/inthat/article/details/127151802
LZ4