欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Zstd 压缩性能分析

程序员文章站 2022-03-23 22:11:17
About ZstdZstd,全称 Zstandard,是 Facebook 于 2016 年开源的新无损压缩算法。与 zlib、lz4、xz 等当前流行的压缩算法不同,Zstd 寻求一种压缩性能与压缩率通吃的方案,而实际上它也确实做到了。在由官方所列出的表格中,可以看到,Zstd 不仅具备优秀的压缩性能,在压缩率上也有非常亮眼的表现。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RXOO1Z8l-1596090419061)(https://engineering.fb...

About Zstd

Zstd,全称 Zstandard,是 Facebook 于 2016 年开源的新无损压缩算法。与 zlib、lz4、xz 等当前流行的压缩算法不同,Zstd 寻求一种压缩性能与压缩率通吃的方案,而实际上它也确实做到了。在由官方所列出的表格中,可以看到,Zstd 不仅具备优秀的压缩性能,在压缩率上也有非常亮眼的表现。

Zstd 压缩性能分析

综合来说,Zstd 具有以下特性:

  • 在压缩性能和压缩率上均有很突出的表现
  • 支持以训练方式生成字典文件,可显著提高对小数据包的压缩率

About Zstd-jni

Zstd-jni,顾名思义,是基于 Zstd 本地库实现的 Java 调用接口。它支持通过 Java 语言实现 Zstd 的压缩与解压缩。

在 Zstd-jni 的三方包中,主要实现了以下功能:

  • 提供静态的压缩与解压缩方法
  • 支持压缩数据的流式传输
  • 支持字典文件的训练与添加

Code Example

下面示例代码将展示 Zstd-jni 的压缩、解压、字典训练等功能:

package com.panda.zstd;

import com.github.luben.zstd.Zstd;
import com.github.luben.zstd.ZstdDictCompress;
import com.github.luben.zstd.ZstdDictDecompress;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * zstd 示例
 *
 * @author panda
 * @date 2020/7/29
 */
public class ZstdDemo {

    private static final Logger LOGGER = LoggerFactory.getLogger(ZstdDemo.class);

    // 训练文件
    private static final String TRAIN_FILE = "C:\\Users\\admin\\Desktop\\train\\train-10000.txt";

    // 待压缩文件
    private static final String COMPRESS_FILE = "C:\\Users\\admin\\Desktop\\train\\test.txt";

    // 压缩等级,以时间换空间
    private static final Integer LEVEL = 10;

    // 解压时字节数组的最大值
    private static final Integer MAX_SIZE = 1000000;

    private static ZstdDictCompress compressDict;

    private static ZstdDictDecompress decompressDict;

    public static void main(String[] args) throws IOException {
        String s = FileUtils.readFileToString(new File(COMPRESS_FILE), StandardCharsets.UTF_8);
        byte[] bytes = s.getBytes(StandardCharsets.UTF_8);

        train();
        compress(bytes);
    }

    public static void train() throws IOException {
        // 初始化词典对象
        String dictContent = FileUtils.readFileToString(new File(TRAIN_FILE), StandardCharsets.UTF_8);
        byte[] dictBytes = dictContent.getBytes(StandardCharsets.UTF_8);
        compressDict = new ZstdDictCompress(dictBytes, LEVEL);
        decompressDict = new ZstdDictDecompress(dictBytes);
    }

    public static void compress(byte[] bytes) {
        LOGGER.info("raw data length: {}", bytes.length);

        // 压缩数据
        long compressBeginTime = System.currentTimeMillis();
        byte[] compressed = Zstd.compress(bytes, compressDict);
        long compressEndTime = System.currentTimeMillis();
        LOGGER.info("compress spend time: {}", compressEndTime - compressBeginTime);
        LOGGER.info("compressed data length: {}", compressed.length);

        // 解压数据
        long decompressBeginTime = System.currentTimeMillis();
        // 第 3 个参数不能小于解压后的字节数组的大小
        byte[] decompressed = Zstd.decompress(compressed, decompressDict, MAX_SIZE);
        long decompressEndTime = System.currentTimeMillis();
        LOGGER.info("decompress spend time: {}", decompressEndTime - decompressBeginTime);
        LOGGER.info("decompressed data length: {}", decompressed.length);
    }
}

Performance Testing

当前,我们具有以下需求场景:使用 Flume 收集与发送日志,在接收到日志后,对日志对象的 body 进行压缩,再传递给下游,以减少网络传输的开销。据此可以了解到,实际上我们是希望通过 Zstd 实现小文件的压缩与解压

在上面我们提到过,Zstd 支持以训练方式生成字典文件,可提高对小数据包的压缩率。显然,这个特性非常适合我们的需求场景。因此,我们决定将字典作为自变量,测试在不同样本集的字典下,Zstd 的压缩性能与压缩率。

通过测验,我们希望能解决以下疑问:

  • Zstd 是否能满足小文件的压缩与解压需求
  • Zstd 的压缩性能如何,是否会造成数据延时
  • 字典的引入能否提高压缩率,如何选择正确的样本集

首先,我们准备如下 4 份字典文件:

  • train-A:表示含有 5000 条样本日志的字典文件
  • train-B:表示含有 10000 条样本日志的字典文件
  • train-C:表示含有 15000 条样本日志的字典文件
  • train-D:表示含有 20000 条样本日志的字典文件

然后,我们输入 10000 行日志数据,对这些字典分别进行性能测验,测验的指标包含压缩率、压缩时间与解压时间。

测验后,对各指标取平均值,计算结果如下表所示:

dict sample num compress ratio(%) compress time(ms) decompress time(ms)
none 0 54.08 0.03 0.10
train-A 5000 81.85 0.15 0.10
train-B 10000 82.20 0.15 0.09
train-C 15000 82.06 0.15 0.09
train-D 20000 81.07 0.15 0.08

注:ratio = 文件原大小 - 压缩后的大小 / 文件原大小。

结合测验过程及测验结果,我们得出以下结论:

  • zstd 可以满足小文件的压缩与解压需求,经压缩-解压后,数据保持无损状态
  • zstd 的压缩性能非常优秀,平均压缩与解压消耗时间甚至未达到毫秒级别,不会造成数据延时
  • 字典引入可以显著提高压缩率,但会在一定程度上影响压缩性能
  • 字典样本集并非越大越好,合适的样本集更能提高压缩率,根据测验结果,建议样本集数量维持在 10000 左右

Reference

本文地址:https://blog.csdn.net/magicpenta/article/details/107689459

相关标签: java 大数据