你觉得这篇文章怎么样? 帮助我们为您提供更好的内容。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
你觉得这篇文章怎么样?
最近在调试一款网络设备,此设备有多路网络连接(大于6路并发),定期1s记录各路带宽的使用量,每60s发送完整的记录给服务器,用以分析时间<>带宽<>流量之间的关联,可以记录网络状态,用户使用量,使用习惯等。每秒1kbytes,60s大约60kbytes。在上传前使用zip打包,发送给java服务后,由后端java服务解压、保存。由爬虫定期做数据挖掘和分析。
前端设备最初为Intel 6550u,i7的性能就是强,所有的操作几乎不占CPU,对用户的带宽也几乎没有影响。后期前端转为Arm cortex-A53 1GHz的时候,问题就来了, zip打包的速度导致上传线程长期阻塞,使用的CPU过高,导致内部DSP处理的数据无法传递给CPU引起DSP error。那么如何能快速的压缩和解压呢?笔者尝试使用了另一种面向字节无损数据压缩算法LZ4。
下面我先简单介绍一下什么是LZ4
LZ4并非新的算法,2011年第一个版本就已经诞生。是一个基于LZ77的面向字节无损数据压缩算法,着重于压缩和解压缩速度。
Linux内核从3.11起,原生实现了LZ4。近期(2019/09/10),Ubuntu的内核团队更是决定从Ubuntu 19.10开始切换到LZ4内核映像压缩,以加快启动时间(之前通常映像是gzip在最后打包)。
在压缩大小方面,GZIP生成最小的压缩内核大小,其次是LZO(比它大16%)和LZ4(比它大25%)。在解压时间上,LZ4比GZIP快7倍以上,LZO比GZIP在x86上快1.25倍左右。即使使用慢速旋转媒体和慢速CPU, LZ4内核的较长的加载时间也会被更快的解压时间所克服。随着媒体速度的加快,GZIP、LZ4和LZO之间的加载时间差减小,解压时间成为主要的速度因素,而LZ4显然是赢家。
LZ4从最初使用C语言制成的参考实现,到现在已经有多种语言的移植和绑定,包括Java、Javacript、Perl、C#、Pytho、Delphi、Go、Rust、Lua等。
在一份评测报告中,LZ4的编码速度达到了memcpy的1/20,解码速度达到惊人的1/3,也就是三个字节的复制运算量就可以还原1字节的内容,是其他编码算法的5倍以上,可见解码效率之高。
Compressor |
Ratio |
Compression |
Decompression |
memcpy |
1.000 |
13700 MB/s |
13700 MB/s |
LZ4 default (v1.9.0) |
2.101 |
780 MB/s |
4970 MB/s |
LZO 2.09 |
2.108 |
670 MB/s |
860 MB/s |
QuickLZ 1.5.0 |
2.238 |
575 MB/s |
780 MB/s |
Snappy 1.1.4 |
2.091 |
565 MB/s |
1950 MB/s |
Zstandard 1.4.0 -1 |
2.883 |
515 MB/s |
1380 MB/s |
LZF v3.6 |
2.073 |
415 MB/s |
910 MB/s |
zlib deflate 1.2.11 -1 |
2.730 |
100 MB/s |
415 MB/s |
LZ4 HC -9 (v1.9.0) |
2.721 |
41 MB/s |
4900 MB/s |
zlib deflate 1.2.11 -6 |
3.099 |
36 MB/s |
445 MB/s |
在另一份测试报告里,综合了多种压缩编码格式的横向比较,
文件压缩尺寸(1到9是传递进的压缩率参数,文件原始尺寸466083840 (445M))
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
124875819 (120M) |
93997047 (90M) |
85618192 (82M) |
72042179 (69M) |
85630688 (82M) |
72069084 (69M) |
165844264 (159M) |
168012430 (161M) |
2 |
119040249 (114M) |
87741348 (84M) |
81480824 (78M) |
70264395 (68M) |
81492504 (78M) |
70282944 (68M) |
165844264 (159M) |
166987891 (160M) |
3 |
114931686 (110M) |
84816957 (81MB) |
79575087 (76MB) |
69015118 (66MB) |
79586568 (76MB) |
69029204 (66MB) |
165844264 (159M) |
166987891 (160M) |
5 |
102328357 (98M) |
81837328 (79M) |
69557610 (67M) |
67879362 (65M) |
69583428 (67M) |
67875988 (65M) |
- |
166987891 (160M) |
7 |
100128597 (96M) |
80197758 (77M) |
67276420 (65M) |
66868212 (64M) |
67294092 (65M) |
66852780 (64M) |
- |
116205578 (111M) |
9 |
99740486 (96M) |
78963640 (76M) |
65841213 (63M) |
65362226 (63M) |
65859432 (63M) |
65372696 (63M) |
- |
114824102 (110M) |
压缩比
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
26.8% |
20.2% |
18.4% |
15.5% |
18.4% |
15.5% |
35.6% |
36.0% |
2 |
25.5% |
18.8% |
17.5% |
15.1% |
17.5% |
15.1% |
35.6% |
35.8% |
3 |
24.7% |
18.2% |
17.1% |
14.8% |
17.1% |
14.8% |
35.6% |
35.8% |
5 |
22.0% |
17.6% |
14.9% |
14.6% |
14.9% |
14.6% |
- |
35.8% |
7 |
21.5% |
17.2% |
14.4% |
14.3% |
14.4% |
14.3% |
- |
24.9% |
9 |
21.4% |
16.9% |
14.1% |
14.0% |
14.1% |
14.0% |
- |
24.6% |
压缩时间
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
8.1s |
58.3s |
31.7s |
4m37s |
32.2s |
4m40s |
1.3s |
1.6s |
2 |
8.5s |
58.4s |
40.7s |
4m49s |
41.9s |
4m53s |
1.4s |
1.6s |
3 |
9.6s |
59.1s |
1m2s |
4m36s |
1m1s |
4m39s |
1.3s |
1.5s |
5 |
14s |
1m1s |
3m5s |
5m |
3m6s |
4m53s |
- |
1.5s |
7 |
21s |
1m2s |
4m14s |
5m52s |
4m13s |
5m57s |
- |
35s |
9 |
33s |
1m3s |
4m48s |
6m40s |
4m51s |
6m40s |
- |
1m5s |
解压时间
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
3.5s |
3.4s |
6.7s |
5.9s |
7.2s |
6.5s |
0.4s |
1.5s |
2 |
3s |
15.7 |
6.3s |
5.6s |
6.8s |
6.3s |
0.3s |
1.4s |
3 |
3.2s |
15.9s |
6s |
5.6s |
6.7s |
6.2s |
0.4s |
1.4s |
5 |
3.2s |
16s |
5.5s |
5.4s |
6.2s |
6s |
- |
1.5s |
7 |
3s |
15s |
5.3s |
5.3s |
5.9s |
5.8s |
- |
1.3s |
9 |
3s |
15s |
5s |
5.1s |
5.6s |
5.6s |
- |
1.2s |
编码时内存使用量
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
0.4MB |
1.1MB |
8.3MB |
12.6MB |
8.3MB |
12.5MB |
12MB |
0.7MB |
2 |
0.4MB |
1.9MB |
15.8MB |
24MB |
15.8MB |
24MB |
12MB |
0.7MB |
3 |
0.4MB |
2.7MB |
30.7MB |
46.9MB |
30.8MB |
47M |
13.2MB |
0.7MB |
5 |
0.4MB |
4.2MB |
93MB |
93MB |
93MB |
93MB |
- |
0.7MB |
7 |
0.4MB |
5.7MB |
185MB |
185MB |
185MB |
185MB |
- |
0.9MB |
9 |
0.4MB |
7.2MB |
672MB |
673MB |
673MB |
673MB |
- |
0.9MB |
解码时内存使用量
gzip |
bzip2 |
lzma |
lzma -e |
xz |
xz -e |
lz4 |
lzop |
|
1 |
0.1MB |
0.3MB |
1MB |
1MB |
1MB |
1MB |
13MB |
0.2MB |
2 |
0.1MB |
0.9MB |
2.1MB |
2.1MB |
2.1MB |
2.1MB |
12MB |
0.2MB |
3 |
0.1MB |
1.1MB |
4.1MB |
4.1MB |
4.0MB |
4.0MB |
13MB |
0.2MB |
5 |
0.1MB |
1.9MB |
8.1MB |
8.1MB |
8.1MB |
8.1MB |
- |
0.2MB |
7 |
0.1MB |
2.6MB |
16MB |
16MB |
16MB |
16MB |
- |
0.2MB |
9 |
0.1MB |
3.4MB |
64MB |
64MB |
64MB |
64MB |
- |
0.2MB |
奇怪的是内存使用量奇高,将在以后的文章中分析。
根据这些评估,可以看出来,LZ4虽然压缩比不高,但是编码和解码速度奇快。在应用场景上,更多的在需要压缩、解压,并且对速度有很高要求的情况。
使用LZ4带来的好处
转换编码为LZ4后,cpu资源占用降低,速度变快,虽然带宽占用增加,但也有限,并且对原先代码结构变更量极低,不需要调整线程优先级,不需要调整系统结构,并且可以统一x86与arm代码库。目前设备运行正常。
LZ4在低功耗,cpu算力低的设备中特别适用,也是linux映像选择的原因,在内容中加载小文件解码的过程比通过emmc、nand、nor flash等直接加载镜像的速度会快的多。