Snappy

SnappyGoogle 开发的压缩和解压缩的库,最初使用 C++ 编写,后来又造了一个 golang 版本的轮子。由于目前该压缩算法还没有放到 go 的标准库中去,所以需要通过 go get -u github.com/golang/snappy 安装。

与其他常见的压缩算法相比,Snappy 存在的目的并不是为了获得最大程度的压缩比,正如其名字所言,它旨在保持合理的压缩比的同时最大限度地提高压缩和解压缩的速度。

Snappy 对数据处理速度上做了很大的优化,但它并不是没有缺点,相对于其他算法来说,Snappy 压缩得到的文件体积会更大一点。如果你更在意压缩速度而不是压缩比的话,Snappy 可能会是一个很好的选择。

compression

下面,我们对比一下 Snappy 压缩算法和其他两种常见的压缩算法( zlibgzip )的性能。首先,我们定一个 Compressor 接口,并使 ZlibGzipSnappy 这三个结构体均实现它。

1
2
3
4
5
6
7
type Zlib struct{}
type Gzip struct{}
type Snappy struct{}

type Compressor interface {
Compress(io.Writer, io.Reader) error
}

zlib

1
2
3
4
5
6
7
8
9
10
11
12
13
func (_ *Zlib) Compress(w io.Writer, r io.Reader) error {
zw, err := zlib.NewWriterLevel(w, zlib.BestSpeed)
if err != nil {
return err
}
defer zw.Close()

_, err = io.Copy(zw, r)
if err != nil {
return err
}
return nil
}

gzip

1
2
3
4
5
6
7
8
9
10
11
12
13
func (_ *Gzip) Compress(w io.Writer, r io.Reader) error {
gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)
if err != nil {
return err
}
defer gw.Close()

_, err = io.Copy(gw, r)
if err != nil {
return err
}
return nil
}

snappy

1
2
3
4
5
6
7
8
9
10
func (_ *Snappy) compress(w io.Writer, r io.Reader) error {
sw := snappy.NewBufferedWriter(w)
defer sw.Close()

_, err := io.Copy(sw, r)
if err != nil {
return err
}
return nil
}

performance

对于压缩的性能,可以从压缩比和压缩时间这两点进行衡量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func main() {
f, err := os.Open("somebigfile")
if err != nil {
log.Fatal(err)
}

fGzip, _ := os.Create("gzip")
fZlib, _ := os.Create("zlib")
fSnappy, _ := os.Create("snappy")

cs := map[compressor]io.Writer{
&Gzip{}: fGzip,
&Zlib{}: fZlib,
&Snappy{}: fSnappy,
}

for c, v := range cs {
t := time.Now()
err := c.compress(v, f)
if err != nil {
fmt.Println(err)
}
d := time.Since(t)
fmt.Printf("method: %s, time spend: %.02f, ratio: %.05f%%\n",
v.Name(),
d.Seconds(),
compressionRatio(f, v))
f.Seek(0, 0)
}
}
1
2
3
4
5
6
7
func compressionRatio(f1, f2 *os.File) float64 {
f1s, _ := f1.Stat()
f1size := f1s.Size()
f2s, _ := f2.Stat()
f2size := f2s.Size()
return float64(f2size) / float64(f1size) * 100
}

Snappy 在速度上来说比 zlibgzip 快得多,但文件相对要大 20%100%。在 64 位模式的 Core i7 处理器上,Snappy 可以达到 250~500 兆每秒的压缩速度,可以说是非常惊人了。

1
2
3
4
$ go run main.go
method: gzip, time spend: 8.38s, ratio: 7.576%
method: zlib, time spend: 9.13s, ratio: 7.576%
method: snappy, time spend: 1.96s, ratio: 18.813%

相比其他的压缩库,Snappy 能在保持特定的压缩率下拥有惊人的压缩速度,压缩普通文本文件的速度是其他库的 1.5-1.7 倍,HTML能达到 2-4 倍,但是对于 JPEGPNG 以及其他的已压缩的数据,压缩速度不会有明显改善。

Pieces of Valuable Programming Knowledges