1 /*
2  * Copyright (c) 2016-present, Yann Collet, 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