DesignSpark Electrical Logolinkedin
菜单 搜寻
提问问题

14 Oct 2019, 7:59

浅论面向字节无损数据压缩算法LZ4在ARM上的应用

最近在调试一款网络设备,此设备有多路网络连接(大于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等直接加载镜像的速度会快的多。

ErosLin 还没写个人简介...

14 Oct 2019, 7:59