Linux压缩算法-zstd

news/2024/7/4 7:21:05

文章目录

  • 概述:
  • ZSTD压缩算法介绍:
  • ZSTD压缩算法下载:
  • ZSTD压缩算法编译:
    • 1、ubuntu(gcc编译):
      • 1.1、直接编译:
      • 1.2、编译库文件:
    • 2、arm(交叉编译库文件):
  • ZSTD压缩算法使用:
    • 1、可执行文件(zstd):
      • 1.1、可执行文件参数说明:
      • 1.2、可执行文件使用:
        • 1.2.1、数据压缩:
        • 1.2.2、数据解压:
        • 1.2.3、版本显示:
    • 2、c代码(gcc编译举例):
      • 2.1、库文件移植:
      • 2.2、配置cmakelists:
      • 2.3、测试代码:
      • 2.4、函数说明:
  • 总结:

概述:

本文讲述的是一种快速无损数据压缩算法(zstd)。

ZSTD压缩算法介绍:

Zstandard,简称zstd,是由Facebook开发的一种快速无损压缩算法,针对zlib级的实时压缩场景和更好的压缩比。

ZSTD压缩算法下载:

ubuntu社区的下载地址:http://security.ubuntu.com/ubuntu/pool/main/libz/libzstd/libzstd_1.5.5+dfsg2.orig.tar.xz

github的下载地址:https://github.com/facebook/zstd

ZSTD压缩算法编译:

1、ubuntu(gcc编译):

1.1、直接编译:

1、进入源码文件下;

2、在终端输入“make”;

3、在/lib路径下生成编译的动态库(.so)和静态库(.a)文件,在/programs路径下生成编译的可执行文件;

动态库:libzstd.so、libzstd.so.1、libzstd.so.1.5.5;

静态库:libzstd.a;

可执行文件:zstd;

使用动态库的“libzstd.so、libzstd.so.1”文件时,需要注意,这两个动态库是软连接,需要将其软链接到“libzstd.so.1.5.5”,同时将3个动态库文件移动到需要使用的库文件路径下,如果是需要在c代码中使用,请看下面c代码使用说明。

1.2、编译库文件:

1、进入源码文件下;

2、在ubuntu终端输入以下命令(此处以gcc为例);

mkdir gcc_lib
make lib CC=gcc -j $(grep "cpu cores" /proc/cpuinfo | wc -l)
make install PREFIX=$(pwd)/gcc_lib

命令解析:

make lib CC=gcc -j $(grep "cpu cores" /proc/cpuinfo | wc -l)

设置编译库文件,同时设置gcc编译器和编译内核数;

make install PREFIX=$(pwd)/gcc_lib

设置库安装位置到新建的文件夹;

3、在/gcc_lib/lib路径下生成编译的动态库(.so)和静态库(.a)文件,在/gcc_lib/include路径下生成对应的头文件,在/gcc_lib/bin路径下生成对应的zstd可执行文件;

2、arm(交叉编译库文件):

1、进入源码文件下;

2、在ubuntu终端输入以下命令(此处以rv1126为例);

mkdir arm_lib
make lib CC=arm-linux-gnueabihf-gcc -j $(grep "cpu cores" /proc/cpuinfo | wc -l) 
make install PREFIX=$(pwd)/arm_lib

命令解析:

make lib CC=arm-linux-gnueabihf-gcc -j $(grep "cpu cores" /proc/cpuinfo | wc -l) 

设置编译库文件,同时设置交叉编译器和编译内核数;

make install PREFIX=$(pwd)/arm_lib

设置库安装位置到新建的文件夹;

3、在/arm_lib/lib路径下生成编译的动态库(.so)和静态库(.a)文件,在/arm_lib/include路径下生成对应的头文件,在/arm_lib/bin路径下生成对应的zstd可执行文件;

ZSTD压缩算法使用:

1、可执行文件(zstd):

1.1、可执行文件参数说明:

Usage: zstd [OPTIONS...] [INPUT... | -] [-o OUTPUT]

Options:
  -o OUTPUT                     将输出写入单个文件 OUTPUT.
  -k, --keep                    保存输入文件(s). [默认] 
  --rm                          成功()压缩后删除输入文件.

  -#                            期望的压缩级别,其中' # '是1到19之间的数字;较低的数字提供更快的压缩,较高的数字产生更好							 的压缩比。(默认值:3)

  -d, --decompress              解压.
  -D DICT                       使用DICT作为压缩或解压缩的字典.

  -f, --force                   禁用输入和输出检查。允许覆盖现有文件;从控制台接收输入,将输出打印到STDOUT,以及在链路、  							  块设备等上操作。无法识别的格式按原样通过.

  -h                            显示简洁的帮助信息并退出.
  -H, --help                    显示完整帮助信息并退出.
  -V, --version                 显示版本号并退出.

1.2、可执行文件使用:

1.2.1、数据压缩:

直接使用/programs/zstd的可执行文件进行数据压缩

1、新建测试文件test.txt

2、在bash终端执行压缩命令

指定输出文件:

./zstd -1 ./test.txt -o ./test_zstd.txt

默认输出文件:

./zstd -1 ./test.txt

命令解析:

-1 :表示压缩等级为1,-# 期望的压缩级别,其中“#”是1到19之间的数字;较低的数字提供更快的压缩,较高的数字产生更好的压缩比。(默认值:3);

./test.txt :表示需要压缩的源文件;

-o ./test_zstd.txt : 表示输出到指定的文件(test_zstd.txt)

3、执行结果

指定输出文件:

./test.txt           : 28.18%   (   110 B =>     31 B, ./test_zstd.txt)   

默认输出文件:

./test.txt           : 28.18%   (   110 B =>     31 B, ./test.txt.zst) 

结果分析:

20.18% :表示压缩比例,31/110=0.2818;

./test_zstd.txt :表示指定的压缩输出文件;

./test.txt.zst :表示默认的压缩输出文件;

1.2.2、数据解压:

1、确定需要解压的数据文件(当前使用上面压缩的文件:test_zstd.txt 、test.txt.zst)

2、在终端输入以下命令

指定的需解压文件及指定输出文件

./zstd -d ./test_zstd.txt -o ./test_de.txt

默认格式的需解压文件及不指定输出文件

./zstd -d ./test.txt.zst

3、执行结果

指定的需解压文件及指定输出文件

./test_zstd.txt     : 110 bytes    

默认格式的需解压文件及不指定输出文件

zstd: ./test.txt already exists; overwrite (y/n) ? y
./test.txt.zst      : 110 bytes           

结果分析:

110 bytes :表示解压后的文件大小;

zstd: ./test.txt already exists; overwrite (y/n) :表示当前目录下存在test.txt文件,询问是否需要覆盖;

1.2.3、版本显示:

在终端输入以下命令:

命令1:

./zstd -V

命令2:

./zstd --version

执行结果:

命令1:

*** Zstandard CLI (64-bit) v1.5.5, by Yann Collet ***

命令2:

*** Zstandard CLI (64-bit) v1.5.5, by Yann Collet ***

2、c代码(gcc编译举例):

2.1、库文件移植:

将 gcc_lib 中的 include 和 lib 文件夹拷贝到需要的程序路径下(如:ThirdParty/gcc/zstd_1.5.5/)

2.2、配置cmakelists:

set(ZSTD_INCLUDE_DIRS ThirdParty/gcc/zstd_1.5.5/include)
set(ZSTD_LIBDIR ThirdParty/gcc/zstd_1.5.5/lib)
include_directories(${ZSTD_INCLUDE_DIRS})
link_directories(${ZSTD_LIBDIR})
set(ZSTD_LIBS libzstd.so)

target_link_libraries(${PROJECT_NAME}
        ${ZSTD_LIBS}
        )

2.3、测试代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include "zstd.h"

#define LOG(fmt,arg...)   printf("[%s]" fmt "\r\n",__FUNCTION__,##arg);

long long get_sys_time_us(void)
{
    long long time_us = 0;
    struct timeval sys_current_time;

    gettimeofday(&sys_current_time, NULL);
    time_us = (long long)sys_current_time.tv_sec * 1000000 + sys_current_time.tv_usec;

    return time_us;
}

void zstd_compress_test(void)
{
    // 压缩
    char *src0 = "12345678901234567890123456789012345678901234567890";
    char dst0[64] = {0};
    int src0_size = strlen(src0) + 1;
    int max_dst0_size = sizeof(dst0);
    int dst0_compress_size = 0;

    LOG("before compress = %s, bytes = %d", src0, src0_size);
    if (src0_size < max_dst0_size)
    {
        long long compress_start_time = get_sys_time_us();
        dst0_compress_size = ZSTD_compress(dst0, max_dst0_size, src0, src0_size, 21);
        long long compress_end_time = get_sys_time_us();
        LOG("after compress = %s, bytes = %d", dst0, (int)strlen(dst0));
        LOG("compress_time = %lld us", compress_end_time - compress_start_time);
    }
    else
    {
        LOG("compress error! src0_size >= max_dst0_size");
    }

    // 解压
    char src1[64] = {0};
    char dst1[64] = {0};
    int compressed_size = dst0_compress_size;
    int max_decompressed_size = sizeof(dst1);
    int dst1_decompress_size = 0;

    if (dst0_compress_size < max_decompressed_size)
    {
        memcpy(src1, dst0, dst0_compress_size);
        LOG("before decompress = %s, bytes = %d", src1, (int)strlen(src1));
    }
    else
    {
        LOG("dst0_compress_size >= max_decompressed_size");
    }

    if (compressed_size < max_decompressed_size)
    {
        long long decompress_start_time = get_sys_time_us();
        dst1_decompress_size = ZSTD_decompress(dst1, max_decompressed_size, src1, compressed_size);
        long long decompress_end_time = get_sys_time_us();
        LOG("after decompress = %s, bytes = %d", dst1, dst1_decompress_size);
        LOG("decompress_time = %lld us", decompress_end_time - decompress_start_time);
    }
    else
    {
        LOG("decompress error! compressed_size >= max_decompressed_size");
    }
}

int main(int argc, char *argv[])
{
    LOG("==================================================================================");
    zstd_compress_test();
    return 0;
}

编译后执行可执行文件生成的结果如下

[main]==================================================================================
[zstd_compress_test]before compress = 12345678901234567890123456789012345678901234567890, bytes = 51
[zstd_compress_test]after compress = (�/� 3�, bytes = 7
[zstd_compress_test]compress_time = 3493 us
[zstd_compress_test]before decompress = (�/� 3�, bytes = 7
[zstd_compress_test]after decompress = 12345678901234567890123456789012345678901234567890, bytes = 51
[zstd_compress_test]decompress_time = 415 us

从测试结果可以得知压缩时间是3493us,压缩字节从51个字节压缩成7个字节;解压时间是415us,解压后的数据和压缩前数据一致;

2.4、函数说明:

压缩函数:
ZSTD_compress( void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
输入:
    dst:存放压缩后数据的地址;
    dstCapacity:存放压缩后数据的大小;
    src:压缩源数据地址;
    srcSize:压缩源数据大小;
    compressionLevel:压缩等级,0-100 ,默认是3,压缩等级越高压缩效率越高,但时间越长,但到达一定的压缩量后压缩效率会无法提升;

输出:
    压缩成功,返回压缩的数据大小,
    压缩失败,返回错误代码(可以使用ZSTD_isError()进行测试)。

解压函数:
ZSTD_decompress( void* dst, size_t dstCapacity, const void* src, size_t compressedSize);
输入:
    dst:存放解压缩后数据的地址;
    dstCapacity:存放解压缩后数据的大小;
    src:解压缩的源数据地址;
    compressedSize:解压缩源数据大小;

输出:
    解压缩成功,返回解压缩的数据大小,
    解压缩失败,返回错误代码(可以使用ZSTD_isError()进行测试)。

总结:

zstd 压缩算法相对于lz4的压缩时间更快,压缩效率更高一些。

免责声明:本文内容含网络参考、作者编写等,内容版权归原作者所有,未经允许,禁止转载。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。


http://lihuaxi.xjx100.cn/news/1920468.html

相关文章

【MYSQL】MYSQL 的学习教程(十)之 InnoDB 锁

数据库为什么需要加锁呢&#xff1f; 如果有多个并发请求存取数据&#xff0c;在数据就可能会产生多个事务同时操作同一行数据。如果并发操作不加控制&#xff0c;不加锁的话&#xff0c;就可能写入了不正确的数据&#xff0c;或者导致读取了不正确的数据&#xff0c;破坏了数…

【开源】基于JAVA的智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…

3D换肤在服装行业的应用

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 通过采用高质量的 3D 模型&#xff0c;企业可以提供更加身临其境的体…

MySQL 和 MySQL2 的区别

MySQL是最流行的开源关系型数据库管理系统,拥有大量的使用者和广泛的应用场景。而MySQL2是MySQL官方团队推出的新一代MySQL驱动&#xff0c;用于取代老版的MySQL模块&#xff0c;提供更好的性能和更丰富的功能。 本文将介绍MySQL2相较于MySQL有哪些优势以及具体的技术区别。 …

Python - 深夜数据结构与算法之 Greedy

目录 一.引言 二.贪心的简介 1.贪心算法 2.适用场景 三.经典算法实战 1.Jump-Game-2 [45] 2.Jump-Game [55] 3.Max-Profit [122] 4.Assign-Cookies [455] 5.Lemonade-Change [860] 四.总结 一.引言 本节带来算法中比较经典的贪心算法&#xff0c;它和动态规划有一定…

HTML的学习记录

<br /> 标签在 HTML 页面中创换行符。 <hr /> 标签在 HTML 页面中创建水平线。 段落是通过 <p> 标签定义的。 浏览器会自动地在段落的前后添加空行。&#xff08;<p> 是块级元素&#xff09; 文本格式 <b>This text is bold</b>字体加粗 …

C#获取windows系统资源使用情况

1.前言 之前有一篇博客介绍如何获取Linux服务器上的资源使用情况《Java 获取服务器资源&#xff08;内存、负载、磁盘容量&#xff09;》&#xff0c;这里介绍如何通过C#获取Window系统的资源使用。 2.获取服务器资源 2.1.内存 [DllImport("kernel32.dll")][retu…

【轻松入门】OpenCV4.8 + QT5.x开发环境搭建

引言 大家好&#xff0c;今天给大家分享一下最新版本OpenCV4.8 QT5 如何一起配置&#xff0c;完成环境搭建的。 下载OpenCV4.8并解压缩 软件版本支持 CMake3.13 或者以上版本 https://cmake.org/ VS2017专业版或者以上版本 QT5.15.2 OpenCV4.8源码包 https://github.com/op…