1 /*
2 * Copyright (c) 2016-2020, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11 #include "config.h"
12
13 /* Define a config for each fast level we want to test with. */
14 #define FAST_LEVEL(x) \
15 param_value_t const level_fast##x##_param_values[] = { \
16 {.param = ZSTD_c_compressionLevel, .value = -x}, \
17 }; \
18 config_t const level_fast##x = { \
19 .name = "level -" #x, \
20 .cli_args = "--fast=" #x, \
21 .param_values = PARAM_VALUES(level_fast##x##_param_values), \
22 }; \
23 config_t const level_fast##x##_dict = { \
24 .name = "level -" #x " with dict", \
25 .cli_args = "--fast=" #x, \
26 .param_values = PARAM_VALUES(level_fast##x##_param_values), \
27 .use_dictionary = 1, \
28 };
29
30 /* Define a config for each level we want to test with. */
31 #define LEVEL(x) \
32 param_value_t const level_##x##_param_values[] = { \
33 {.param = ZSTD_c_compressionLevel, .value = x}, \
34 }; \
35 config_t const level_##x = { \
36 .name = "level " #x, \
37 .cli_args = "-" #x, \
38 .param_values = PARAM_VALUES(level_##x##_param_values), \
39 }; \
40 config_t const level_##x##_dict = { \
41 .name = "level " #x " with dict", \
42 .cli_args = "-" #x, \
43 .param_values = PARAM_VALUES(level_##x##_param_values), \
44 .use_dictionary = 1, \
45 };
46
47 #define PARAM_VALUES(pv) \
48 { .data = pv, .size = sizeof(pv) / sizeof((pv)[0]) }
49
50 #include "levels.h"
51
52 #undef LEVEL
53 #undef FAST_LEVEL
54
55 static config_t no_pledged_src_size = {
56 .name = "no source size",
57 .cli_args = "",
58 .param_values = PARAM_VALUES(level_0_param_values),
59 .no_pledged_src_size = 1,
60 };
61
62 static param_value_t const ldm_param_values[] = {
63 {.param = ZSTD_c_enableLongDistanceMatching, .value = 1},
64 };
65
66 static config_t ldm = {
67 .name = "long distance mode",
68 .cli_args = "--long",
69 .param_values = PARAM_VALUES(ldm_param_values),
70 };
71
72 static param_value_t const mt_param_values[] = {
73 {.param = ZSTD_c_nbWorkers, .value = 2},
74 };
75
76 static config_t mt = {
77 .name = "multithreaded",
78 .cli_args = "-T2",
79 .param_values = PARAM_VALUES(mt_param_values),
80 };
81
82 static param_value_t const mt_ldm_param_values[] = {
83 {.param = ZSTD_c_nbWorkers, .value = 2},
84 {.param = ZSTD_c_enableLongDistanceMatching, .value = 1},
85 };
86
87 static config_t mt_ldm = {
88 .name = "multithreaded long distance mode",
89 .cli_args = "-T2 --long",
90 .param_values = PARAM_VALUES(mt_ldm_param_values),
91 };
92
93 static param_value_t mt_advanced_param_values[] = {
94 {.param = ZSTD_c_nbWorkers, .value = 2},
95 {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
96 };
97
98 static config_t mt_advanced = {
99 .name = "multithreaded with advanced params",
100 .cli_args = "-T2 --no-compress-literals",
101 .param_values = PARAM_VALUES(mt_advanced_param_values),
102 };
103
104 static param_value_t const small_wlog_param_values[] = {
105 {.param = ZSTD_c_windowLog, .value = 10},
106 };
107
108 static config_t small_wlog = {
109 .name = "small window log",
110 .cli_args = "--zstd=wlog=10",
111 .param_values = PARAM_VALUES(small_wlog_param_values),
112 };
113
114 static param_value_t const small_hlog_param_values[] = {
115 {.param = ZSTD_c_hashLog, .value = 6},
116 {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt},
117 };
118
119 static config_t small_hlog = {
120 .name = "small hash log",
121 .cli_args = "--zstd=hlog=6,strat=7",
122 .param_values = PARAM_VALUES(small_hlog_param_values),
123 };
124
125 static param_value_t const small_clog_param_values[] = {
126 {.param = ZSTD_c_chainLog, .value = 6},
127 {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt},
128 };
129
130 static config_t small_clog = {
131 .name = "small chain log",
132 .cli_args = "--zstd=clog=6,strat=7",
133 .param_values = PARAM_VALUES(small_clog_param_values),
134 };
135
136 static param_value_t const uncompressed_literals_param_values[] = {
137 {.param = ZSTD_c_compressionLevel, .value = 3},
138 {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
139 };
140
141 static config_t uncompressed_literals = {
142 .name = "uncompressed literals",
143 .cli_args = "-3 --no-compress-literals",
144 .param_values = PARAM_VALUES(uncompressed_literals_param_values),
145 };
146
147 static param_value_t const uncompressed_literals_opt_param_values[] = {
148 {.param = ZSTD_c_compressionLevel, .value = 19},
149 {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_uncompressed},
150 };
151
152 static config_t uncompressed_literals_opt = {
153 .name = "uncompressed literals optimal",
154 .cli_args = "-19 --no-compress-literals",
155 .param_values = PARAM_VALUES(uncompressed_literals_opt_param_values),
156 };
157
158 static param_value_t const huffman_literals_param_values[] = {
159 {.param = ZSTD_c_compressionLevel, .value = -1},
160 {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_lcm_huffman},
161 };
162
163 static config_t huffman_literals = {
164 .name = "huffman literals",
165 .cli_args = "--fast=1 --compress-literals",
166 .param_values = PARAM_VALUES(huffman_literals_param_values),
167 };
168
169 static param_value_t const explicit_params_param_values[] = {
170 {.param = ZSTD_c_checksumFlag, .value = 1},
171 {.param = ZSTD_c_contentSizeFlag, .value = 0},
172 {.param = ZSTD_c_dictIDFlag, .value = 0},
173 {.param = ZSTD_c_strategy, .value = (int)ZSTD_greedy},
174 {.param = ZSTD_c_windowLog, .value = 18},
175 {.param = ZSTD_c_hashLog, .value = 21},
176 {.param = ZSTD_c_chainLog, .value = 21},
177 {.param = ZSTD_c_targetLength, .value = 100},
178 };
179
180 static config_t explicit_params = {
181 .name = "explicit params",
182 .cli_args = "--no-check --no-dictID --zstd=strategy=3,wlog=18,hlog=21,clog=21,tlen=100",
183 .param_values = PARAM_VALUES(explicit_params_param_values),
184 };
185
186 static config_t const* g_configs[] = {
187
188 #define FAST_LEVEL(x) &level_fast##x, &level_fast##x##_dict,
189 #define LEVEL(x) &level_##x, &level_##x##_dict,
190 #include "levels.h"
191 #undef LEVEL
192 #undef FAST_LEVEL
193
194 &no_pledged_src_size,
195 &ldm,
196 &mt,
197 &mt_ldm,
198 &small_wlog,
199 &small_hlog,
200 &small_clog,
201 &explicit_params,
202 &uncompressed_literals,
203 &uncompressed_literals_opt,
204 &huffman_literals,
205 &mt_advanced,
206 NULL,
207 };
208
209 config_t const* const* configs = g_configs;
210
config_skip_data(config_t const * config,data_t const * data)211 int config_skip_data(config_t const* config, data_t const* data) {
212 return config->use_dictionary && !data_has_dict(data);
213 }
214
config_get_level(config_t const * config)215 int config_get_level(config_t const* config)
216 {
217 param_values_t const params = config->param_values;
218 size_t i;
219 for (i = 0; i < params.size; ++i) {
220 if (params.data[i].param == ZSTD_c_compressionLevel)
221 return (int)params.data[i].value;
222 }
223 return CONFIG_NO_LEVEL;
224 }
225
config_get_zstd_params(config_t const * config,uint64_t srcSize,size_t dictSize)226 ZSTD_parameters config_get_zstd_params(
227 config_t const* config,
228 uint64_t srcSize,
229 size_t dictSize)
230 {
231 ZSTD_parameters zparams = {};
232 param_values_t const params = config->param_values;
233 int level = config_get_level(config);
234 if (level == CONFIG_NO_LEVEL)
235 level = 3;
236 zparams = ZSTD_getParams(
237 level,
238 config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : srcSize,
239 dictSize);
240 for (size_t i = 0; i < params.size; ++i) {
241 unsigned const value = params.data[i].value;
242 switch (params.data[i].param) {
243 case ZSTD_c_contentSizeFlag:
244 zparams.fParams.contentSizeFlag = value;
245 break;
246 case ZSTD_c_checksumFlag:
247 zparams.fParams.checksumFlag = value;
248 break;
249 case ZSTD_c_dictIDFlag:
250 zparams.fParams.noDictIDFlag = !value;
251 break;
252 case ZSTD_c_windowLog:
253 zparams.cParams.windowLog = value;
254 break;
255 case ZSTD_c_chainLog:
256 zparams.cParams.chainLog = value;
257 break;
258 case ZSTD_c_hashLog:
259 zparams.cParams.hashLog = value;
260 break;
261 case ZSTD_c_searchLog:
262 zparams.cParams.searchLog = value;
263 break;
264 case ZSTD_c_minMatch:
265 zparams.cParams.minMatch = value;
266 break;
267 case ZSTD_c_targetLength:
268 zparams.cParams.targetLength = value;
269 break;
270 case ZSTD_c_strategy:
271 zparams.cParams.strategy = (ZSTD_strategy)value;
272 break;
273 default:
274 break;
275 }
276 }
277 return zparams;
278 }
279