常见压缩算法性能和压缩率对比 LZ4 LZO ZSTD SNAPPY

article/2025/7/21 16:56:03

网传压缩算法对比表

算法压缩率压缩速度解压速度支持流式压缩适用场景
LZ4极快极快实时数据压缩、日志压缩、内存缓存等
Zstandard文件压缩、网络传输、数据库备份等
Brotli很高中等静态资源压缩(HTML、CSS、JS)等
LZO极快嵌入式系统、实时数据压缩
Snappy中等日志压缩、内存缓存、网络传输

性能实测

在这里插入图片描述

./compress_test syslog.txtLZ4 0 comp:   64.669 ms  decom:   15.282 ms  Size: 85.906 MB  Ratio: 17.186 %
LZ4 1 comp:   65.662 ms  decom:   15.046 ms  Size: 85.906 MB  Ratio: 17.186 %
LZO 0 comp:   65.834 ms  decom:   51.929 ms  Size: 85.906 MB  Ratio: 17.936 %
LZO 1 comp:   61.834 ms  decom:   50.462 ms  Size: 85.906 MB  Ratio: 17.936 %
Zstd 0 comp:   71.713 ms  decom:   31.642 ms  Size: 85.906 MB  Ratio: 9.230 %
Zstd 1 comp:   93.255 ms  decom:   47.457 ms  Size: 85.906 MB  Ratio: 9.230 %
Brotli 0 comp:  156.201 ms  decom:  115.879 ms  Size: 85.906 MB  Ratio: 13.189 %
Brotli 1 comp:  127.775 ms  decom:  104.258 ms  Size: 85.906 MB  Ratio: 13.189 %
Snappy 0 comp:   84.727 ms  decom:   52.499 ms  Size: 85.906 MB  Ratio: 18.220 %
Snappy 1 comp:   82.503 ms  decom:   52.898 ms  Size: 85.906 MB  Ratio: 18.220 %

对于一个系统日志文件,LZ4 LZO速度最快, 压缩率zstd遥遥领先,综合性价比 Zstd完胜。

安装与使用

LZ4

编译

git clone https://github.com/lz4/lz4.git
cd lz4
make

使用

ckun@DESKTOP-PODAH1A:~/ws/compress/test$ rm -f log.lz4
ckun@DESKTOP-PODAH1A:~/ws/compress/test$ time ./lz4 syslog -T1 log.lz4
Compressed 3290808339 bytes into 567183342 bytes ==> 17.24%real    0m5.855s
user    0m4.636s
sys     0m1.910s

Zstd

git clone https://github.com/facebook/zstd.git
cd zstd
make

Brotli

git clone https://github.com/google/brotli.git
cd brotlimkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make

LZO

wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz
tar -xvzf lzo-2.10.tar.gz
cd lzo-2.10
mkdir build
cd build
cmake -DENABLE_SHARED=ON ..
make

Snappy

git clone https://github.com/google/snappy.git
cd snappy
git submodule update --init
mkdir build
cd build 
cmake ..
make

测试程序


#include <iostream>
#include <fstream>
#include <vector>
#include <chrono>
#include <cstring>
#include <lz4.h>
#include <lzo/lzo1x.h>
#include <zstd.h>
#include <brotli/encode.h>
#include <brotli/decode.h>
#include <snappy.h>#include <iomanip> 
// Helper function to calculate checksum (simple Adler-32 implementation)
uint32_t calculate_checksum(const std::vector<char>& data) {uint32_t a = 1, b = 0;for (char c : data) {a = (a + static_cast<uint8_t>(c)) % 65521;b = (b + a) % 65521;}return (b << 16) | a;
}// Read file into memory
std::vector<char> read_file(const std::string& filename) {std::ifstream file(filename, std::ios::binary | std::ios::ate);if (!file) {throw std::runtime_error("Failed to open file: " + filename);}std::streamsize size = file.tellg();file.seekg(0, std::ios::beg);std::vector<char> buffer(size);if (!file.read(buffer.data(), size)) {throw std::runtime_error("Failed to read file: " + filename);}return buffer;
}// Test LZ4 compression and decompression
void test_lz4(const std::vector<char>& input, int i) {//std::cout << "Testing LZ4..." << std::endl;// Allocate buffersint max_compressed_size = LZ4_compressBound(input.size());std::vector<char> compressed(max_compressed_size);std::vector<char> decompressed(input.size());// Compressauto start = std::chrono::high_resolution_clock::now();int compressed_size = LZ4_compress_default(input.data(), compressed.data(), input.size(), max_compressed_size);auto end = std::chrono::high_resolution_clock::now();if (compressed_size <= 0) {throw std::runtime_error("LZ4 compression failed");}auto compression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Decompressstart = std::chrono::high_resolution_clock::now();int decompressed_size = LZ4_decompress_safe(compressed.data(), decompressed.data(), compressed_size, decompressed.size());end = std::chrono::high_resolution_clock::now();if (decompressed_size != input.size()) {throw std::runtime_error("LZ4 decompression failed");}auto decompression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Verify checksumuint32_t original_checksum = calculate_checksum(input);uint32_t decompressed_checksum = calculate_checksum(decompressed);if (original_checksum != decompressed_checksum) {throw std::runtime_error("LZ4 checksum mismatch");}// Output resultsprintf("LZ4 %d comp: %8.3lf ms  decom: %8.3lf ms  Size: %.3f MB  Ratio: %.3f %%\n",i, (compression_time / 1000.0), (decompression_time / 1000.0),(input.size() / (1024.0 * 1024.0)),(double) (static_cast<double>(compressed_size) / input.size()) * 100);
}// Test LZO compression and decompression
void test_lzo(const std::vector<char>& input, int i) {//std::cout << "Testing LZO..." << std::endl;// Initialize LZOif (lzo_init() != LZO_E_OK) {throw std::runtime_error("LZO initialization failed");}// Allocate buffersstd::vector<char> compressed(input.size() + input.size() / 16 + 64 + 3);std::vector<char> decompressed(input.size());std::vector<unsigned char> wrkmem(LZO1X_1_MEM_COMPRESS);// Compressauto start = std::chrono::high_resolution_clock::now();lzo_uint compressed_size;int r = lzo1x_1_compress(reinterpret_cast<const unsigned char*>(input.data()), input.size(),reinterpret_cast<unsigned char*>(compressed.data()), &compressed_size, wrkmem.data());auto end = std::chrono::high_resolution_clock::now();if (r != LZO_E_OK) {throw std::runtime_error("LZO compression failed");}auto compression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Decompressstart = std::chrono::high_resolution_clock::now();lzo_uint decompressed_size;r = lzo1x_decompress(reinterpret_cast<const unsigned char*>(compressed.data()), compressed_size,reinterpret_cast<unsigned char*>(decompressed.data()), &decompressed_size, nullptr);end = std::chrono::high_resolution_clock::now();if (r != LZO_E_OK || decompressed_size != input.size()) {throw std::runtime_error("LZO decompression failed");}auto decompression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Verify checksumuint32_t original_checksum = calculate_checksum(input);uint32_t decompressed_checksum = calculate_checksum(decompressed);if (original_checksum != decompressed_checksum) {throw std::runtime_error("LZO checksum mismatch");}// Output results// std::cout << "LZO " << i << " ";// std::cout << "comp: " << (compression_time / 1000.0) << " ms  "//           << "decom: " << (decompression_time / 1000.0) << " ms  "//           << "Size: " << (input.size() / (1024.0 * 1024.0)) << " MB  "//           << "Ratio: " << (static_cast<double>(compressed_size) / input.size()) * 100 << " %" //           << std::endl;printf("LZO %d comp: %8.3lf ms  decom: %8.3lf ms  Size: %.3f MB  Ratio: %.3f %%\n",i, (compression_time / 1000.0), (decompression_time / 1000.0),(input.size() / (1024.0 * 1024.0)),(double) (static_cast<double>(compressed_size) / input.size()) * 100);
}void test_zstd(const std::vector<char>& input, int i) {// Allocate bufferssize_t max_compressed_size = ZSTD_compressBound(input.size());std::vector<char> compressed(max_compressed_size);std::vector<char> decompressed(input.size());// Compressauto start = std::chrono::high_resolution_clock::now();size_t compressed_size = ZSTD_compress(compressed.data(), max_compressed_size, input.data(), input.size(), 1);auto end = std::chrono::high_resolution_clock::now();if (ZSTD_isError(compressed_size)) {throw std::runtime_error("Zstd compression failed: " + std::string(ZSTD_getErrorName(compressed_size)));}auto compression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Decompressstart = std::chrono::high_resolution_clock::now();size_t decompressed_size = ZSTD_decompress(decompressed.data(), decompressed.size(), compressed.data(), compressed_size);end = std::chrono::high_resolution_clock::now();if (ZSTD_isError(decompressed_size) || decompressed_size != input.size()) {throw std::runtime_error("Zstd decompression failed: " + std::string(ZSTD_getErrorName(decompressed_size)));}auto decompression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Verify checksumuint32_t original_checksum = calculate_checksum(input);uint32_t decompressed_checksum = calculate_checksum(decompressed);if (original_checksum != decompressed_checksum) {throw std::runtime_error("Zstd checksum mismatch");}// Output resultsprintf("Zstd %d comp: %8.3lf ms  decom: %8.3lf ms  Size: %.3f MB  Ratio: %.3f %%\n",i, (compression_time / 1000.0), (decompression_time / 1000.0),(input.size() / (1024.0 * 1024.0)),(double) (static_cast<double>(compressed_size) / input.size()) * 100);
}void test_brotli(const std::vector<char>& input, int i) {// Allocate bufferssize_t max_compressed_size = BrotliEncoderMaxCompressedSize(input.size());std::vector<uint8_t> compressed(max_compressed_size);std::vector<uint8_t> decompressed(input.size());// Compressauto start = std::chrono::high_resolution_clock::now();size_t compressed_size = max_compressed_size;if (!BrotliEncoderCompress(0, BROTLI_DEFAULT_WINDOW, BROTLI_MODE_GENERIC,input.size(), reinterpret_cast<const uint8_t*>(input.data()),&compressed_size, compressed.data())) {throw std::runtime_error("Brotli compression failed");}auto end = std::chrono::high_resolution_clock::now();auto compression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Decompressstart = std::chrono::high_resolution_clock::now();size_t decompressed_size = decompressed.size();if (BrotliDecoderDecompress(compressed_size, compressed.data(),&decompressed_size, decompressed.data()) != BROTLI_DECODER_RESULT_SUCCESS) {throw std::runtime_error("Brotli decompression failed");}end = std::chrono::high_resolution_clock::now();auto decompression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Verify checksumuint32_t original_checksum = calculate_checksum(input);uint32_t decompressed_checksum = calculate_checksum(std::vector<char>(decompressed.begin(), decompressed.end()));if (original_checksum != decompressed_checksum) {throw std::runtime_error("Brotli checksum mismatch");}// Output resultsprintf("Brotli %d comp: %8.3lf ms  decom: %8.3lf ms  Size: %.3f MB  Ratio: %.3f %%\n",i, (compression_time / 1000.0), (decompression_time / 1000.0),(input.size() / (1024.0 * 1024.0)),(double) (static_cast<double>(compressed_size) / input.size()) * 100);
}void test_snappy(const std::vector<char>& input, int i) {// Allocate buffersstd::string compressed;std::string decompressed;// Compressauto start = std::chrono::high_resolution_clock::now();snappy::Compress(input.data(), input.size(), &compressed);auto end = std::chrono::high_resolution_clock::now();auto compression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Decompressstart = std::chrono::high_resolution_clock::now();if (!snappy::Uncompress(compressed.data(), compressed.size(), &decompressed)) {throw std::runtime_error("Snappy decompression failed");}end = std::chrono::high_resolution_clock::now();auto decompression_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();// Verify checksumuint32_t original_checksum = calculate_checksum(input);uint32_t decompressed_checksum = calculate_checksum(std::vector<char>(decompressed.begin(), decompressed.end()));if (original_checksum != decompressed_checksum) {throw std::runtime_error("Snappy checksum mismatch");}// Output resultsprintf("Snappy %d comp: %8.3lf ms  decom: %8.3lf ms  Size: %.3f MB  Ratio: %.3f %%\n",i, (compression_time / 1000.0), (decompression_time / 1000.0),(input.size() / (1024.0 * 1024.0)),(double) (static_cast<double>(compressed.size()) / input.size()) * 100);
}template <typename Func>
void run_test(Func func, const std::vector<char>& input, int times) {for (int i = 0; i < times; ++i) {func(input, i);}
}int main(int argc, char* argv[]) {if (argc != 2) {std::cerr << "Usage: " << argv[0] << " <file>" << std::endl;return 1;}std::cout << std::fixed << std::setprecision(3); try {// Read file into memorystd::vector<char> input = read_file(argv[1]);// Calculate checksumuint32_t checksum = calculate_checksum(input);std::cout << "Original Checksum: " << checksum << std::endl;// Test LZ4run_test(test_lz4, input, 2);// Test LZOrun_test(test_lzo, input, 2);run_test(test_zstd, input, 2);// Test Brotlirun_test(test_brotli, input, 2);// Test Snappyrun_test(test_snappy, input, 2);} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;return 1;}return 0;
}

Makefile

TARGET = compress_testSRCS = $(wildcard *.cpp)CC = g++CFLAGS += -g -O2 -I../lz4/lib -I../lzo-2.10/include -I../zstd/lib \-I../brotli/c/include -I../snappy LDFLAGS += -lyaml-cpp  -L../lz4/lib -llz4 \-L../lzo-2.10/build -llzo2 -lz \-L../zstd/lib -lzstd \-L../brotli/build -lbrotlicommon -lbrotlidec -lbrotlienc \-L../snappy/build -lsnappy
all: $(TARGET)$(TARGET): $(SRCS)$(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS).PHONY: clean
clean:rm $(TARGET)

运行

export LD_LIBRARY_PATH=../lz4/lib:../lzo-2.10/build:../zstd/lib:../brotli/build/:../snappy/build$ ldd compress_testlinux-vdso.so.1 (0x00007ffdb71cf000)liblz4.so.1 => ../lz4/lib/liblz4.so.1 (0x00007fc26045a000)liblzo2.so.2 => ../lzo-2.10/build/liblzo2.so.2 (0x00007fc260427000)libzstd.so.1 => ../zstd/lib/libzstd.so.1 (0x00007fc260330000)libbrotlidec.so.1 => ../brotli/build/libbrotlidec.so.1 (0x00007fc260321000)libbrotlienc.so.1 => ../brotli/build/libbrotlienc.so.1 (0x00007fc260268000)libsnappy.so.1 => ../snappy/build/libsnappy.so.1 (0x00007fc260259000)libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc260026000)libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc260006000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc25fddd000)libbrotlicommon.so.1 => ../brotli/build/libbrotlicommon.so.1 (0x00007fc25fdb7000)libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc25fcd0000)/lib64/ld-linux-x86-64.so.2 (0x00007fc260498000)./compress_test file

http://www.hkcw.cn/article/sbMaeLKjRs.shtml

相关文章

Tkinter软件——显示txt标签的目标水平边框图像

代码&#xff1a; import tkinter as tk from tkinter import filedialog from tkinter import messagebox import cv2 from PIL import Image, ImageTk import osclass ImageBoxApp:def __init__(self, master):self.master masterself.master.title("Image Box Drawer…

学习vue3阶段性复习(插槽,Pinia,生命周期)

目录 插槽(匿名插槽&#xff0c;具名插槽) 插槽概述 匿名插槽 具名插槽 Pinia(统一管理&#xff0c;共享数据&#xff09; pinia概述 安装和使用Pinia 1 使用命令下载Pinia 2 再main.js中导入&#xff0c;注册到vue框架中 3使用pinia 持久化存储插件 1 第一步&…

创建环境 镜像报错UnavailableInvalidChannel: HTTP 404 NOT FOUND for channel...

报错&#xff1a;Platform: win-64 Collecting package metadata (repodata.json): failed UnavailableInvalidChannel: HTTP 404 NOT FOUND for channel anaconda/pkgs/main <https://mirrors.aliyun.com/anaconda/pkgs/main> The channel is not accessible or is inva…

小狼毫输入法雾凇拼音输入方案辅码由默认的部件拆字/拼音输入方案修改为五笔画方案

搜狗拼音输入法不单单是弹出广告的问题&#xff0c;还有收集输入习惯等隐私的嫌疑。所以最近彻底删除了这个输入法&#xff0c;改安装了小狼毫输入法。关于小狼毫输入法的安装和使用网上已经有了无数文章&#xff0c;我这里就不重复了。在试用多个拼音方案后&#xff0c;最终我…

车载通信网络 --- OSI模型中传输层、会话层、表示层和应用层

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

Dify理论+部署+实战

概述 一个功能强大的开源AI应用开发平台&#xff0c;融合后端即服务&#xff08;Backend as Service&#xff09;和LLMOps理念&#xff0c;使开发者能够快速搭建生产级的生成式AI应用。 核心优势 直观的用户界面&#xff1a;提供简洁明了的操作界面&#xff0c;使得用户能够…

Java类和对象详解

文章目录 1.初步认识2.类的定义与实例化2.1 类的定义2.2 类的实例化与使用 3.this关键字4.对象的构造和初始化4.1 默认初始化4.2 就地初始化4.3 构造方法初始化 5.对象的打印6.包的理解6.1 导入包中的类6.2 自定义包6.3 包访问权限 7.封装7.1 访问限定符详解 8.static关键字8.1…

【Go语言】Fyne GUI 库使用指南 (面向有经验开发者)

引言 Fyne 是一个使用 Go 语言编写的、易于使用的跨平台 GUI 工具包和应用程序 API。它旨在通过单一代码库构建在桌面和移动设备上运行的应用程序。本文档面向有一定 Go 语言开发经验的开发者&#xff0c;将详细介绍 Fyne 最新版的核心功能&#xff0c;包括基础组件、布局系统…

1. pytorch手写数字预测

1. pytorch手写数字预测 1.背景2.准备数据集2.定义模型3.dataloader和训练4.训练模型5.测试模型6.保存模型 1.背景 因为自身的研究方向是多模态目标跟踪&#xff0c;突然对其他的视觉方向产生了兴趣&#xff0c;所以心血来潮的回到最经典的视觉任务手写数字预测上来&#xff0…

武警智能兵器室系统架构设计与关键技术解析

在现代化武警部队建设中&#xff0c;武器弹药的安全管理与快速响应能力直接影响部队战斗力。本文基于某实战化智能兵器室建设案例&#xff0c;深入解析其系统架构设计、关键技术实现及创新管理机制&#xff0c;为安防领域提供可借鉴的解决方案。 整体拓扑结构 系统采用分层分布…

HTML5 列表、表格与媒体元素、页面结构分析

1. 列表 无序列表 有序列表 定义列表 列表对比 2. 表格 跨列 跨行 跨行和跨列 3. HTML5的媒体元素 视频元素 注意&#xff1a;autoplay现在很多浏览器不支持了&#xff01; 音频元素 4. 页面结构分析 5. 总结

中文文本分析及词云生成

一、代码解析&#xff08;按执行顺序&#xff09; 1. 库导入 import jieba # 中文分词工具 from wordcloud import WordCloud # 词云生成器 from collections import Counter # 词频统计 import matplotlib.pyplot as plt # 可视化 import numpy as np # 图像矩阵处理 f…

芯片手册解读

一&#xff1a; 1.这是一款差分转单端的芯片&#xff1a; 2.给出了逻辑高低的识别门限&#xff1a;并不是大于100mv和小于-100mv就识别不到了——而是大于100mv和小于-100mv都可以识别到&#xff0c;手册的意思仅仅代表门限节点而已&#xff0c;完全可以在进入门限后的其他电…

LangChain-Tool和Agent结合智谱AI大模型应用实例2

1.Tool(工具) 定义与功能 单一功能模块:Tool是完成特定任务的独立工具,每个工具专注于一项具体的操作,例如:搜索、计算、API调用等 无决策能力:工具本身不决定何时被调用,仅在被触发时执行预设操作 输入输出明确:每个工具需明确定义输入、输出参数及格式 2.Agent(…

专业级图片分割解决方案

在日常处理图片的过程中&#xff0c;我们常常会遇到需要将一张图分割成多个小图的情况。这一款高效又实用的图片分割工具——它操作简单、功能强大&#xff0c;关键是完全免费开源&#xff0c;适合所有有图像处理需求的朋友&#xff01; 在使用之前&#xff0c;先花几分钟把它…

Re--题

一&#xff0e;[NSSCTF 2022 Spring Recruit]easy C 直接看for循环&#xff0c;异或 写代码 就得到了flag easy_Re 二&#xff0e;[SWPUCTF 2021 新生赛]非常简单的逻辑题 先对这段代码进行分析 flag xxxxxxxxxxxxxxxxxxxxx s wesyvbniazxchjko1973652048$-&*&l…

iOS 集成网易云信IM

云信官方文档在这 看官方文档的时候&#xff0c;版本选择最新的V10。 1、CocoPods集成 pod NIMSDK_LITE 2、AppDelegate.m添加头文件 #import <NIMSDK/NIMSDK.h> 3、初始化 NIMSDKOption *mrnn_option [NIMSDKOption optionWithAppKey:"6f6568e354026d2d658a…

边缘计算网关支撑医院供暖系统高效运维的本地化计算与边缘决策

一、项目背景 医院作为人员密集的特殊场所&#xff0c;对供暖系统的稳定性和高效性有着极高的要求。其供暖换热站传统的人工现场监控方式存在诸多弊端&#xff0c;如人员值守成本高、数据记录不及时不准确、故障发现和处理滞后、能耗难以有效监测和控制等&#xff0c;难以满足…

Google Earth Pro 7.3 中文绿色版 - 谷歌地球专业版(精准定位,清晰查看您家位置)

谷歌卫星高清地图 下载链接&#xff1a;https://pan.quark.cn/s/c6069864c9f3 Google Earth Pro-7.3.6.9796-x64 Google Earth WinMac安装版 GoogleEarthProPortable googleearthpromac-intel-7.3.6.10155 GoogleEarthProWin-7.3.6.10155 GoogleEarthProWin-x64-7.3.6.10…

【工作笔记】 WSL开启报错

【工作笔记】 WSL开启报错 时间&#xff1a;2025年5月30日16:50:42 1.现象 Installing, this may take a few minutes... WslRegisterDistribution failed with error: 0x80370114 Error: 0x80370114 ??????????????????Press any key to continue...