学到了,原来 gzip 是种`连续分块`的压缩算法

发布时间 2023-10-09 16:10:39作者: ahfuzhang

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


我想要表述的是:假设有 10 mb的数据使用 gzip 算法来压缩。
有这样可能的做法:

  • 分配 10mb 的缓冲区,一次压缩 10mb
  • 分配 1mb 的缓冲区,每次压缩 1mb,分为十次压缩

如果压缩后的数据有统一的头部信息,那么压缩后的数据必须统一存放,每一次后续的压缩都需要去修改这个头部。
反之,如果每次压缩都是独立的块,那么前一次压缩与后一次压缩就是完全不关联的。在实际应用中,就可以做流式处理。

经过实验发现,gzip 压缩后的数据块格式,就像我上面说的第二种,是连续分块的。

下面是我的实验代码:

// 两个函数所产生的文件内容完全一样
func testWriteFile() {
	f, _ := os.Create("part_test.txt.gz")
	_, _ = f.Write(fasthttp.AppendGzipBytesLevel(nil, []byte(`0123456789`), fasthttp.CompressBestSpeed))
	_, _ = f.Write(fasthttp.AppendGzipBytesLevel(nil, []byte(`abcdefghijk`), fasthttp.CompressBestSpeed))
	_, _ = f.Write(fasthttp.AppendGzipBytesLevel(nil, []byte(html), fasthttp.CompressBestSpeed))
	_, _ = f.Write(fasthttp.AppendGzipBytesLevel(nil, []byte(js), fasthttp.CompressBestSpeed))
	f.Close()
}

func testWriteFile1() {
	f, _ := os.Create("part_test1.txt.gz")
	buf := fasthttp.AppendGzipBytesLevel(nil, []byte(`0123456789`), fasthttp.CompressBestSpeed)
	buf = fasthttp.AppendGzipBytesLevel(buf, []byte(`abcdefghijk`), fasthttp.CompressBestSpeed)
	buf = fasthttp.AppendGzipBytesLevel(buf, []byte(html), fasthttp.CompressBestSpeed)
	buf = fasthttp.AppendGzipBytesLevel(buf, []byte(js), fasthttp.CompressBestSpeed)
	_, _ = f.Write(buf)
	f.Close()
}

这样的好处是:在一个 http 服务器中,页面输出的过程中,部分输出内容可以提前压缩好,这样就能够节约整体的压缩带来的 cpu 消耗。