網(wǎng)站首頁 編程語言 正文
前言
上一篇探索了LZ4的壓縮和解壓性能,以及對LZ4和ZSTD的壓縮、解壓性能進(jìn)行了橫向?qū)Ρ取N哪┑淖詈笠步o了一個(gè)彩蛋:任意長度的字符串都可以被ZSTD、LZ4之類的壓縮算壓縮得很好嗎?
本篇我們就來一探究竟。
一、通用算法的短字符壓縮
開門見山,我們使用一段比較短的文本:Narrator: It is raining today. So, Peppa and George cannot??play outside.Peppa: Daddy, it's stopped raining.
使用ZSTD與LZ4分別壓縮一下上面這段短文本。下面分別是它們的壓縮結(jié)果。
ZSTD:
LZ4:
對短文本的壓縮,zstd的壓縮率很低,lz4壓縮后的文本長度盡然超過了原有字符串的長度。這是為什么?說實(shí)話在這之前我也沒想到。
引用兩位大佬的名言:
Are you ok???
What's your problem?
二、短字符串壓縮
從上面的結(jié)果可以得知,任何壓縮算法都有它的使用場景,并不是所有長度的字符串都適合被某種算法壓縮。一般原因是通用壓縮算法維護(hù)了被壓縮字符串的,用于字符串還原的相關(guān)數(shù)據(jù)結(jié)構(gòu),而這些數(shù)據(jù)結(jié)構(gòu)的長度超過了被壓縮短字符串的自身長度。
那么問題來了,“我真的有壓縮短字符串的需求,我想體驗(yàn)壓縮的極致感,怎么辦?”。
短字符壓縮算法它來了。這里挑選了3種比較優(yōu)異的短字符壓縮算法,分別是smaz,shoco,以及壓軸的unisox2。跟前兩章一樣,還是從壓縮率,壓縮和解壓縮性能的角度,一起看看他們在短字符壓縮場景的各自表現(xiàn)吧。
(1)Smaz
1、Smaz的壓縮和解壓縮
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "smaz.h"
using namespace std;
int main()
{
int buf_len;
int com_size;
int decom_size;
char com_buf[4096] = {0};
char decom_buf[4096] = {0};
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
com_size = smaz_compress(str_buf, buf_len, com_buf, 4096);
cout << "text size:" << buf_len << endl;
cout << "compress text size:" << com_size << endl;
cout << "compress ratio:" << (float)buf_len / (float)com_size << endl << endl;
decom_size = smaz_decompress(com_buf, com_size, decom_buf, 4096);
cout << "decompress text size:" << decom_size << endl;
if(strncmp(str_buf, decom_buf, buf_len)) {
cout << "decompress text is not equal to source text" << endl;
}
return 0;
}
執(zhí)行結(jié)果如下:
通過smaz壓縮后的短字符串長度為77,和源字符串相比,減少了30Byte。
2、Smaz的壓縮和解壓縮性能
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sys/time.h>
#include "smaz.h"
using namespace std;
int main()
{
int cnt = 0;
int buf_len;
int com_size;
int decom_size;
timeval st, et;
char *com_ptr = NULL;
char* decom_ptr = NULL;
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
gettimeofday(&st, NULL);
while(1) {
com_ptr = (char *)malloc(buf_len);
com_size = smaz_compress(str_buf, buf_len, com_ptr, buf_len);
free(com_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
cout << endl <<"compress per second:" << cnt/10 << " times" << endl;
cnt = 0;
com_ptr = (char *)malloc(buf_len);
com_size = smaz_compress(str_buf, buf_len, com_ptr, buf_len);
gettimeofday(&st, NULL);
while(1) {
// decompress length not more than origin buf length
decom_ptr = (char *)malloc(buf_len + 1);
decom_size = smaz_decompress(com_ptr, com_size, decom_ptr, buf_len + 1);
// check decompress length
if(buf_len != decom_size) {
cout << "decom error" << endl;
}
free(decom_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
cout << "decompress per second:" << cnt/10 << " times" << endl << endl;
free(com_ptr);
return 0;
}
結(jié)果如何?
壓縮性能在40w條/S,解壓在百萬級,好像還不錯(cuò)哈!
(2)Shoco
1、Shoco的壓縮和解壓縮
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "shoco.h"
using namespace std;
int main()
{
int buf_len;
int com_size;
int decom_size;
char com_buf[4096] = {0};
char decom_buf[4096] = {0};
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
com_size = shoco_compress(str_buf, buf_len, com_buf, 4096);
cout << "text size:" << buf_len << endl;
cout << "compress text size:" << com_size << endl;
cout << "compress ratio:" << (float)buf_len / (float)com_size << endl << endl;
decom_size = shoco_decompress(com_buf, com_size, decom_buf, 4096);
cout << "decompress text size:" << decom_size << endl;
if(strncmp(str_buf, decom_buf, buf_len)) {
cout << "decompress text is not equal to source text" << endl;
}
return 0;
}
執(zhí)行結(jié)果如下:
通過shoco壓縮后的短字符串長度為86,和源字符串相比,減少了21Byte。壓縮率比smaz要低。
?2、Shoco的壓縮和解壓縮性能
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sys/time.h>
#include "shoco.h"
using namespace std;
int main()
{
int cnt = 0;
int buf_len;
int com_size;
int decom_size;
timeval st, et;
char *com_ptr = NULL;
char* decom_ptr = NULL;
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
gettimeofday(&st, NULL);
while(1) {
com_ptr = (char *)malloc(buf_len);
com_size = shoco_compress(str_buf, buf_len, com_ptr, buf_len);
free(com_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
cout << endl <<"compress per second:" << cnt/10 << " times" << endl;
cnt = 0;
com_ptr = (char *)malloc(buf_len);
com_size = shoco_compress(str_buf, buf_len, com_ptr, buf_len);
gettimeofday(&st, NULL);
while(1) {
// decompress length not more than origin buf length
decom_ptr = (char *)malloc(buf_len + 1);
decom_size = shoco_decompress(com_ptr, com_size, decom_ptr, buf_len + 1);
// check decompress length
if(buf_len != decom_size) {
cout << "decom error" << endl;
}
free(decom_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
cout << "decompress per second:" << cnt/10 << " times" << endl << endl;
free(com_ptr);
return 0;
}
執(zhí)行結(jié)果如何呢?
holy shit!壓縮和解壓縮居然都達(dá)到了驚人的百萬級。就像算法作者們自己說的一樣:“在長字符串壓縮領(lǐng)域,shoco不想與通用壓縮算法競爭,我們的優(yōu)勢是短字符的快速壓縮,雖然壓縮率很爛!”。這樣說,好像也沒毛病。
(3)Unisox2
我們再來看看unisox2呢。
1、Unisox2的壓縮和解壓縮
#include <stdio.h>
#include <string.h>
#include "unishox2.h"
int main()
{
int buf_len;
int com_size;
int decom_size;
char com_buf[4096] = {0};
char decom_buf[4096] = {0};
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
com_size = unishox2_compress_simple(str_buf, buf_len, com_buf);
printf("text size:%d\n", buf_len);
printf("compress text size:%d\n", com_size);
printf("compress ratio:%f\n\n", (float)buf_len / (float)com_size);
decom_size = unishox2_decompress_simple(com_buf, com_size, decom_buf);
printf("decompress text size:%d\n", decom_size);
if(strncmp(str_buf, decom_buf, buf_len)) {
printf("decompress text is not equal to source text\n");
}
return 0;
}
結(jié)果如下:
通過Unisox2壓縮后的短字符串長度為67,和源字符串相比,減少了40Byte,相當(dāng)于是打了6折啊!不錯(cuò)不錯(cuò)。
?2、Unisox2的壓縮和解壓縮性能
Unisox2的壓縮能力目前來看是三者中最好的,如果他的壓縮和解壓性能也不錯(cuò)的話,那就真的就比較完美了。再一起看看Unisox2的壓縮和解壓性能吧!
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <sys/time.h>
#include "unishox2.h"
int main()
{
int cnt = 0;
int buf_len;
int com_size;
int decom_size;
struct timeval st, et;
char *com_ptr = NULL;
char* decom_ptr = NULL;
char str_buf[1024] = "Narrator: It is raining today. So, Peppa and George cannot play outside.Peppa: Daddy, it's stopped raining.";
buf_len = strlen(str_buf);
gettimeofday(&st, NULL);
while(1) {
com_ptr = (char *)malloc(buf_len);
com_size = unishox2_compress_simple(str_buf, buf_len, com_ptr);
free(com_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
printf("\ncompress per second:%d times\n", cnt/10);
cnt = 0;
com_ptr = (char *)malloc(buf_len);
com_size = unishox2_compress_simple(str_buf, buf_len, com_ptr);
gettimeofday(&st, NULL);
while(1) {
// decompress length not more than origin buf length
decom_ptr = (char *)malloc(buf_len + 1);
decom_size = unishox2_decompress_simple(com_ptr, com_size, decom_ptr);
// check decompress length
if(buf_len != decom_size) {
printf("decom error\n");
}
free(decom_ptr);
cnt++;
gettimeofday(&et, NULL);
if(et.tv_sec - st.tv_sec >= 10) {
break;
}
}
printf("decompress per second:%d times\n\n", cnt/10);
free(com_ptr);
return 0;
}
執(zhí)行結(jié)果如下:
事與愿違,Unisox2雖然有三個(gè)算法中最好的壓縮率,可是卻也擁有最差的壓縮和解壓性能。跟前兩章分析的不謀而合:有高壓縮率,就會損失自身的壓縮性能,兩者不可兼得。
三、總結(jié)
本篇分享了smaz,shoco,unisox2三種短字符串壓縮算法,分別探索了它們各自的壓縮率與壓縮和解壓縮性能,結(jié)果如下表所示。
表1
shoco的壓縮率最低,但是擁有最高的壓縮和解壓速率;smaz居中;unisox2擁有最高的壓縮率,可是它的壓縮和解壓性能最低。
結(jié)論與前兩章有關(guān)長字符串壓縮的分析不謀而合:擁有高壓縮率,就會損失自身的壓縮性能,兩者不可兼得。
實(shí)際使用還是看自身需求和環(huán)境吧。如果適當(dāng)壓縮就好,那就可以選用shoco,畢竟性能高;想要節(jié)約更多的空間,那就選擇smaz或者unisox2。
原文鏈接:https://www.cnblogs.com/t-bar/p/16506289.html
相關(guān)推薦
- 2022-09-22 原型鏈及原型鏈的作用/構(gòu)造函數(shù),原型對象,實(shí)例對象的三角關(guān)系
- 2022-05-02 詳解在Python中使用OpenCV進(jìn)行直線檢測_python
- 2022-08-17 解決Git推送錯(cuò)誤non-fast-forward的方法_相關(guān)技巧
- 2022-03-14 如何在Git hub上快速查找合適的項(xiàng)目(如何在github上找到自己想要的代碼)
- 2022-10-09 玩轉(zhuǎn)Go命令行工具Cobra_Golang
- 2023-01-21 Python調(diào)整數(shù)組形狀如何實(shí)現(xiàn)_python
- 2022-10-04 在shell腳本中激活conda虛擬環(huán)境的方法總結(jié)_linux shell
- 2022-03-06 C語言之快速排序算法(遞歸Hoare版)介紹_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支