官网: 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在压缩率上略微逊色, 但是在解压速度上有着惊人的优势 (大概是gzip的3倍(多次测试对比))。因为压缩时高效的多核利用,再加上惊艳的解压,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内核压缩)
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。
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)
}
LZ4 压缩算法在压缩数据时会在数据前面添加一个 4 字节的魔数,用于表示该数据经过了 LZ4 压缩。这个魔数的值为固定的 0x184D2204。
收到的数据前 4 个字节的值为 0x184D2204,则可以判断该数据是经过 LZ4 压缩的。反之,如果数据前 4 个字节的值不是 0x184D2204,则该数据很可能没有经过 LZ4 压缩。
import "encoding/binary"
func isLZ4Compressed(data []byte) bool {
if len(data) < 4 {
return false
}
magic := uint32(0x184D2204)
return binary.LittleEndian.Uint32(data[:4]) == magic
}
todo,未测试验证!
速度与压缩比如何兼得?压缩算法在构建部署中的优化
参考URL: https://tech.meituan.com/2021/01/07/pack-gzip-zstd-lz4.html
速度之王 — LZ4压缩算法(一)
参考URL: https://www.cnblogs.com/aiwz/p/6333317.html