ZSTD多线程压缩

发布时间 2023-04-22 16:22:02作者: Akatsuki-

测试代码:

 1 // main.cpp
 2 // 
 3 
 4 #include <iostream>
 5 #include <fstream>
 6 #include <vector>
 7 #include <chrono>
 8 #include <thread>
 9 #include "./zstd/lib/zstd.h"
10 
11 using byte = uint8_t;
12 using buffer = std::vector<byte>;
13 
14 using std::chrono::milliseconds;
15 using std::chrono::steady_clock;
16 using std::chrono::duration_cast;
17 
18 buffer read_file(const char* path)
19 {
20     std::ifstream s(path, std::ios::binary);
21     if (!s)
22         return {};
23     s.seekg(0, std::ios::end);
24     auto length = s.tellg();
25     s.seekg(0, std::ios::beg);
26     if (!length)
27         return {};
28     buffer buf(length, 0);
29     auto ptr = (char*)buf.data();
30     s.read(ptr, length);
31     if (!s)
32         return {};
33     return buf;
34 }
35 
36 int main()
37 {
38     // 1. 读取测试数据到内存
39     auto input = read_file("test.bmp");
40     // 2. 预估输出缓冲区大小
41     auto bufSize = ZSTD_compressBound(input.size());
42     // 3. 创建输出缓冲区
43     buffer output(bufSize, 0);
44     // 4. 设置压缩参数
45     auto level = 19; // ZSTD 多线程压缩时将 level 设置为 19 效率较高
46     auto num_threads = std::thread::hardware_concurrency(); // 获取CPU线程数
47     // 5. 创建压缩上下文
48     auto ctx = ZSTD_createCCtx();
49     ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, level);
50     ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, num_threads);
51     // 6. 执行压缩
52     auto tp1 = steady_clock::now();
53     auto result = ZSTD_compress2(ctx, output.data(), output.size(), input.data(), input.size());
54     auto tp2 = steady_clock::now();
55     // 7. 销毁压缩上下文
56     ZSTD_freeCCtx(ctx);
57     ctx = nullptr;
58 
59     if (ZSTD_isError(result))
60     {
61         std::cout << "error" << std::endl;
62         return 1;
63     }
64 
65     auto time = duration_cast<milliseconds>(tp2 - tp1).count();
66 
67     std::cout << "original: " << input.size() << std::endl;
68     std::cout << "compressed: " << result << std::endl;
69     std::cout << "elapsed: " << time << "ms" << std::endl;
70     std::cout << "level: " << level << std::endl;
71     std::cout << "threads: " << num_threads << std::endl;
72 
73     return 0;
74 }

测试代码使用VS2022编译通过。

编译ZSTD时确保预处理器有 ZSTD_MULTITHREAD=1 定义,可以直接引用源码文件夹里的 libzstd 项目。

结论:启用多线程压缩时, level <= 19 基本可以吃满CPU, level == 20 效率打五折, level >= 21 跟单线程没什么区别。