本文来自博客园,作者:T-BARBARIANS,博文严禁转载,转载必究!
前言
上一篇探索了LZ4的压缩和解压性能,以及对LZ4和ZSTD的压缩、解压性能进行了横向对比。文末的最后也给了一个彩蛋:任意长度的字符串都可以被ZSTD、LZ4之类的压缩算法压缩得很好吗?
本篇我们就来一探究竟。
一、通用算法的短字符压缩
开门见山,我们使用一段比较短的文本:Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.
使用ZSTD与LZ4分别压缩一下上面这段短文本。下面分别是它们的压缩结果。
ZSTD:
LZ4:
对短文本的压缩,zstd的压缩率很低,lz4压缩后的文本长度尽然超过了原有字符串的长度。这是为什么?说实话在这之前我也没想到。
引用两位大佬的名言:
Are you ok?
What's your problem?
二、短字符串压缩
从上面的结果可以得知,任何压缩算法都有它的使用场景,并不是所有长度的字符串都适合被某种算法压缩。一般原因是通用压缩算法维护了被压缩字符串的,用于字符串还原的相关数据结构,而这些数据结构的长度超过了被压缩短字符串的自身长度。
那么问题来了,“我真的有压缩短字符串的需求,我想体验压缩的极致感,怎么办?”。
短字符压缩算法它来了。这里挑选了3种比较优异的短字符压缩算法,分别是smaz,shoco,以及压轴的unisox2。跟前两章一样,还是从压缩率,压缩和解压缩性能的角度,一起看看他们在短字符压缩场景的各自表现吧。
(1)Smaz
1、Smaz的压缩和解压缩
1 #include
2 #include [span style="color: rgba(0, 0, 255, 1)">string.h>
3 #include
4 #include "smaz.h"
5
6 using namespace std;
7
8 int main()
9 {
10 int buf_len;
11 int com_size;
12 int decom_size;
13
14 char com_buf【4096】 = {0};
15 char decom_buf【4096】 = {0};
16
17 char str_buf【1024】 = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
18
19 buf_len = strlen(str_buf);
20 com_size = smaz_compress(str_buf, buf_len, com_buf, 4096);
21
22 cout [ "text size:" [ buf_len [ endl;
23 cout [ "compress text size:" [ com_size [ endl;
24 cout [ "compress ratio:" [ (float)buf_len / (float)com_size [ endl [ endl;
25
26 decom_size = smaz_decompress(com_buf, com_size, decom_buf, 4096);
27 cout [ "decompress text size:" [ decom_size [ endl;
28
29 if(strncmp(str_buf, decom_buf, buf_len)) {
30 cout [ "decompress text is not equal to source text" [ endl;
31 }
32
33 return 0;
34 }
执行结果如下:
通过smaz压缩后的短字符串长度为77,和源字符串相比,减少了30Byte。
2、Smaz的压缩和解压缩性能
1 #include
2 #include [span style="color: rgba(0, 0, 255, 1)">string.h>
3 #include
4 #include
5 #include "smaz.h"
6
7 using namespace std;
8
9 int main()
10 {
11 int cnt = 0;
12 int buf_len;
13 int com_size;
14 int decom_size;
15
16 timeval st, et;
17
18 char com_ptr = NULL;
19 char decom_ptr = NULL;
20
21 char str_buf【1024】 = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
22
23 buf_len = strlen(str_buf);
24 gettimeofday(st, NULL);
25 while(1) {
26
27 com_ptr = (char )malloc(buf_len);
28 com_size = smaz_compress(str_buf, buf_len, com_ptr, buf_len);
29
30 free(com_ptr);
31 cnt++;
32
33 gettimeofday(et, NULL);
34 if(et.tv_sec - st.tv_sec >= 10) {
35 break;
36 }
37 }
38
39 cout [ endl ["compress per second:" [ cnt/10 [ " times" [ endl;
40
41 cnt = 0;
42 com_ptr = (char )malloc(buf_len);
43 com_size = smaz_compress(str_buf, buf_len, com_ptr, buf_len);
44
45 gettimeofday(st, NULL);
46 while(1) {
47
48 // decompress length not more than origin buf length
49 decom_ptr = (char )malloc(buf_len + 1);
50 decom_size = smaz_decompress(com_ptr, com_size, decom_ptr, buf_len + 1);
51
52 // check decompress length
53 if(buf_len != decom_size) {
54 cout [ "decom error" [ endl;
55 }
56
57 free(decom_ptr);
58 cnt++;
59
60 gettimeofday(et, NULL);
61 if(et.tv_sec - st.tv_sec >= 10) {
62 break;
63 }
64 }//代码效果参考:http://www.ezhiqi.com/bx/art_3591.html
65
66 cout [ "decompress per second:" [ cnt/10 [ " times" [ endl [ endl;
67
68 free(com_ptr);
69 return 0;
70 }
结果如何?
压缩性能在40w条/S,解压在百万级,好像还不错哈!
(2)Shoco
1、Shoco的压缩和解压缩
1 #include
2 #include [span style="color: rgba(0, 0, 255, 1)">string.h>
3 #include
4 #include "shoco.h"
5
6 using namespace std;
7
8 int main()
9 {
10 int buf_len;
11 int com_size;
12 int decom_size;
13
14 char com_buf【4096】 = {0};
15 char decom_buf【4096】 = {0};
16
17 char str_buf【1024】 = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
18
19 buf_len = strlen(str_buf);
20 com_size = shoco_compress(str_buf, buf_len, com_buf, 4096);
21
22 cout [ "text size:" [ buf_len [ endl;
23 cout [ "compress text size:" [ com_size [ endl;
24 cout [ "compress ratio:" [ (float)buf_len / (float)com_size [ endl [ endl;
25
26 decom_size = shoco_decompress(com_buf, com_size, decom_buf, 4096);
27 cout [ "decompress text size:" [ decom_size [ endl;
28
29 if(strncmp(str_buf, decom_buf, buf_len)) {
30 cout [ "decompress text is not equal to source text" [ endl;
31 }
32
33 return 0;
34 }
执行结果如下:
通过shoco压缩后的短字符串长度为86,和源字符串相比,减少了21Byte。压缩率比smaz要低。
2、Shoco的压缩和解压缩性能
1 #include
2 #include [span style="color: rgba(0, 0, 255, 1)">string.h>
3 #include
4 #include
5 #include "shoco.h"
6
7 using namespace std;
8
9 int main()
10 {
11 int cnt = 0;
12 int buf_len;
13 int com_size;
14 int decom_size;
15
16 timeval st, et;
17
18 char com_ptr = NULL;
19 char decom_ptr = NULL;
20
21 char str_buf【1024】 = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
22
23 buf_len = strlen(str_buf);
24 gettimeofday(st, NULL);
25 while(1) {
26
27 com_ptr = (char )malloc(buf_len);
28 com_size = shoco_compress(str_buf, buf_len, com_ptr, buf_len);
29
30 free(com_ptr);
31 cnt++;
32
33 gettimeofday(et, NULL);
34 if(et.tv_sec - st.tv_sec >= 10) {
35 break;
36 }
37 }
38
39 cout [ endl ["compress per second:" [ cnt/10 [ " times" [ endl;
40
41 cnt = 0;
42 com_ptr = (char *)malloc(buf_len);
43 com_size = shoco_compress(str_buf, buf_len, com_ptr, buf_len);
44
45 gettimeofday(st, NULL);
46 while(1) {
47
48 // decompress length not more than origin buf length
<span style="color: rgba(0, 128, 128