1 1.1 christos /* 2 1.1 christos * Copyright (c) Meta Platforms, Inc. and affiliates. 3 1.1 christos * All rights reserved. 4 1.1 christos * 5 1.1 christos * This source code is licensed under both the BSD-style license (found in the 6 1.1 christos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7 1.1 christos * in the COPYING file in the root directory of this source tree). 8 1.1 christos * You may select, at your option, one of the above-listed licenses. 9 1.1 christos */ 10 1.1 christos 11 1.1 christos #include "config.h" 12 1.1 christos 13 1.1 christos /* Define a config for each fast level we want to test with. */ 14 1.1 christos #define FAST_LEVEL(x) \ 15 1.1 christos param_value_t const level_fast##x##_param_values[] = { \ 16 1.1 christos {.param = ZSTD_c_compressionLevel, .value = -x}, \ 17 1.1 christos }; \ 18 1.1 christos config_t const level_fast##x = { \ 19 1.1 christos .name = "level -" #x, \ 20 1.1 christos .cli_args = "--fast=" #x, \ 21 1.1 christos .param_values = PARAM_VALUES(level_fast##x##_param_values), \ 22 1.1 christos }; \ 23 1.1 christos config_t const level_fast##x##_dict = { \ 24 1.1 christos .name = "level -" #x " with dict", \ 25 1.1 christos .cli_args = "--fast=" #x, \ 26 1.1 christos .param_values = PARAM_VALUES(level_fast##x##_param_values), \ 27 1.1 christos .use_dictionary = 1, \ 28 1.1 christos }; 29 1.1 christos 30 1.1 christos /* Define a config for each level we want to test with. */ 31 1.1 christos #define LEVEL(x) \ 32 1.1 christos param_value_t const level_##x##_param_values[] = { \ 33 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 34 1.1 christos }; \ 35 1.1 christos param_value_t const level_##x##_param_values_dms[] = { \ 36 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 37 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 38 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach}, \ 39 1.1 christos }; \ 40 1.1 christos param_value_t const level_##x##_param_values_dds[] = { \ 41 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 42 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 1}, \ 43 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach}, \ 44 1.1 christos }; \ 45 1.1 christos param_value_t const level_##x##_param_values_dictcopy[] = { \ 46 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 47 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 48 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceCopy}, \ 49 1.1 christos }; \ 50 1.1 christos param_value_t const level_##x##_param_values_dictload[] = { \ 51 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 52 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 53 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceLoad}, \ 54 1.1 christos }; \ 55 1.1 christos config_t const level_##x = { \ 56 1.1 christos .name = "level " #x, \ 57 1.1 christos .cli_args = "-" #x, \ 58 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values), \ 59 1.1 christos }; \ 60 1.1 christos config_t const level_##x##_dict = { \ 61 1.1 christos .name = "level " #x " with dict", \ 62 1.1 christos .cli_args = "-" #x, \ 63 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values), \ 64 1.1 christos .use_dictionary = 1, \ 65 1.1 christos }; \ 66 1.1 christos config_t const level_##x##_dict_dms = { \ 67 1.1 christos .name = "level " #x " with dict dms", \ 68 1.1 christos .cli_args = "-" #x, \ 69 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values_dms), \ 70 1.1 christos .use_dictionary = 1, \ 71 1.1 christos .advanced_api_only = 1, \ 72 1.1 christos }; \ 73 1.1 christos config_t const level_##x##_dict_dds = { \ 74 1.1 christos .name = "level " #x " with dict dds", \ 75 1.1 christos .cli_args = "-" #x, \ 76 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values_dds), \ 77 1.1 christos .use_dictionary = 1, \ 78 1.1 christos .advanced_api_only = 1, \ 79 1.1 christos }; \ 80 1.1 christos config_t const level_##x##_dict_copy = { \ 81 1.1 christos .name = "level " #x " with dict copy", \ 82 1.1 christos .cli_args = "-" #x, \ 83 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values_dictcopy), \ 84 1.1 christos .use_dictionary = 1, \ 85 1.1 christos .advanced_api_only = 1, \ 86 1.1 christos }; \ 87 1.1 christos config_t const level_##x##_dict_load = { \ 88 1.1 christos .name = "level " #x " with dict load", \ 89 1.1 christos .cli_args = "-" #x, \ 90 1.1 christos .param_values = PARAM_VALUES(level_##x##_param_values_dictload), \ 91 1.1 christos .use_dictionary = 1, \ 92 1.1 christos .advanced_api_only = 1, \ 93 1.1 christos }; 94 1.1 christos 95 1.1 christos /* Define a config specifically to test row hash based levels and settings. 96 1.1 christos */ 97 1.1 christos #define ROW_LEVEL(x, y) \ 98 1.1 christos param_value_t const row_##y##_level_##x##_param_values[] = { \ 99 1.1 christos {.param = ZSTD_c_useRowMatchFinder, .value = y}, \ 100 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 101 1.1 christos }; \ 102 1.1 christos param_value_t const row_##y##_level_##x##_param_values_dms[] = { \ 103 1.1 christos {.param = ZSTD_c_useRowMatchFinder, .value = y}, \ 104 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 105 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 106 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach}, \ 107 1.1 christos }; \ 108 1.1 christos param_value_t const row_##y##_level_##x##_param_values_dds[] = { \ 109 1.1 christos {.param = ZSTD_c_useRowMatchFinder, .value = y}, \ 110 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 111 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 1}, \ 112 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach}, \ 113 1.1 christos }; \ 114 1.1 christos param_value_t const row_##y##_level_##x##_param_values_dictcopy[] = { \ 115 1.1 christos {.param = ZSTD_c_useRowMatchFinder, .value = y}, \ 116 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 117 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 118 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceCopy}, \ 119 1.1 christos }; \ 120 1.1 christos param_value_t const row_##y##_level_##x##_param_values_dictload[] = { \ 121 1.1 christos {.param = ZSTD_c_useRowMatchFinder, .value = y}, \ 122 1.1 christos {.param = ZSTD_c_compressionLevel, .value = x}, \ 123 1.1 christos {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0}, \ 124 1.1 christos {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceLoad}, \ 125 1.1 christos }; \ 126 1.1 christos config_t const row_##y##_level_##x = { \ 127 1.1 christos .name = "level " #x " row " #y, \ 128 1.1 christos .cli_args = "-" #x, \ 129 1.1 christos .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values), \ 130 1.1 christos .advanced_api_only = 1, \ 131 1.1 christos }; \ 132 1.1 christos config_t const row_##y##_level_##x##_dict_dms = { \ 133 1.1 christos .name = "level " #x " row " #y " with dict dms", \ 134 1.1 christos .cli_args = "-" #x, \ 135 1.1 christos .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dms), \ 136 1.1 christos .use_dictionary = 1, \ 137 1.1 christos .advanced_api_only = 1, \ 138 1.1 christos }; \ 139 1.1 christos config_t const row_##y##_level_##x##_dict_dds = { \ 140 1.1 christos .name = "level " #x " row " #y " with dict dds", \ 141 1.1 christos .cli_args = "-" #x, \ 142 1.1 christos .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dds), \ 143 1.1 christos .use_dictionary = 1, \ 144 1.1 christos .advanced_api_only = 1, \ 145 1.1 christos }; \ 146 1.1 christos config_t const row_##y##_level_##x##_dict_copy = { \ 147 1.1 christos .name = "level " #x " row " #y" with dict copy", \ 148 1.1 christos .cli_args = "-" #x, \ 149 1.1 christos .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dictcopy), \ 150 1.1 christos .use_dictionary = 1, \ 151 1.1 christos .advanced_api_only = 1, \ 152 1.1 christos }; \ 153 1.1 christos config_t const row_##y##_level_##x##_dict_load = { \ 154 1.1 christos .name = "level " #x " row " #y " with dict load", \ 155 1.1 christos .cli_args = "-" #x, \ 156 1.1 christos .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dictload), \ 157 1.1 christos .use_dictionary = 1, \ 158 1.1 christos .advanced_api_only = 1, \ 159 1.1 christos }; 160 1.1 christos 161 1.1 christos #define PARAM_VALUES(pv) \ 162 1.1 christos { .data = pv, .size = sizeof(pv) / sizeof((pv)[0]) } 163 1.1 christos 164 1.1 christos #include "levels.h" 165 1.1 christos 166 1.1 christos #undef LEVEL 167 1.1 christos #undef FAST_LEVEL 168 1.1 christos #undef ROW_LEVEL 169 1.1 christos 170 1.1 christos static config_t no_pledged_src_size = { 171 1.1 christos .name = "no source size", 172 1.1 christos .cli_args = "", 173 1.1 christos .param_values = PARAM_VALUES(level_0_param_values), 174 1.1 christos .no_pledged_src_size = 1, 175 1.1 christos }; 176 1.1 christos 177 1.1 christos static config_t no_pledged_src_size_with_dict = { 178 1.1 christos .name = "no source size with dict", 179 1.1 christos .cli_args = "", 180 1.1 christos .param_values = PARAM_VALUES(level_0_param_values), 181 1.1 christos .no_pledged_src_size = 1, 182 1.1 christos .use_dictionary = 1, 183 1.1 christos }; 184 1.1 christos 185 1.1 christos static param_value_t const ldm_param_values[] = { 186 1.1 christos {.param = ZSTD_c_enableLongDistanceMatching, .value = ZSTD_ps_enable}, 187 1.1 christos }; 188 1.1 christos 189 1.1 christos static config_t ldm = { 190 1.1 christos .name = "long distance mode", 191 1.1 christos .cli_args = "--long", 192 1.1 christos .param_values = PARAM_VALUES(ldm_param_values), 193 1.1 christos }; 194 1.1 christos 195 1.1 christos static param_value_t const mt_param_values[] = { 196 1.1 christos {.param = ZSTD_c_nbWorkers, .value = 2}, 197 1.1 christos }; 198 1.1 christos 199 1.1 christos static config_t mt = { 200 1.1 christos .name = "multithreaded", 201 1.1 christos .cli_args = "-T2", 202 1.1 christos .param_values = PARAM_VALUES(mt_param_values), 203 1.1 christos }; 204 1.1 christos 205 1.1 christos static param_value_t const mt_ldm_param_values[] = { 206 1.1 christos {.param = ZSTD_c_nbWorkers, .value = 2}, 207 1.1 christos {.param = ZSTD_c_enableLongDistanceMatching, .value = ZSTD_ps_enable}, 208 1.1 christos }; 209 1.1 christos 210 1.1 christos static config_t mt_ldm = { 211 1.1 christos .name = "multithreaded long distance mode", 212 1.1 christos .cli_args = "-T2 --long", 213 1.1 christos .param_values = PARAM_VALUES(mt_ldm_param_values), 214 1.1 christos }; 215 1.1 christos 216 1.1 christos static param_value_t mt_advanced_param_values[] = { 217 1.1 christos {.param = ZSTD_c_nbWorkers, .value = 2}, 218 1.1 christos {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable}, 219 1.1 christos }; 220 1.1 christos 221 1.1 christos static config_t mt_advanced = { 222 1.1 christos .name = "multithreaded with advanced params", 223 1.1 christos .cli_args = "-T2 --no-compress-literals", 224 1.1 christos .param_values = PARAM_VALUES(mt_advanced_param_values), 225 1.1 christos }; 226 1.1 christos 227 1.1 christos static param_value_t const small_wlog_param_values[] = { 228 1.1 christos {.param = ZSTD_c_windowLog, .value = 10}, 229 1.1 christos }; 230 1.1 christos 231 1.1 christos static config_t small_wlog = { 232 1.1 christos .name = "small window log", 233 1.1 christos .cli_args = "--zstd=wlog=10", 234 1.1 christos .param_values = PARAM_VALUES(small_wlog_param_values), 235 1.1 christos }; 236 1.1 christos 237 1.1 christos static param_value_t const small_hlog_param_values[] = { 238 1.1 christos {.param = ZSTD_c_hashLog, .value = 6}, 239 1.1 christos {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt}, 240 1.1 christos }; 241 1.1 christos 242 1.1 christos static config_t small_hlog = { 243 1.1 christos .name = "small hash log", 244 1.1 christos .cli_args = "--zstd=hlog=6,strat=7", 245 1.1 christos .param_values = PARAM_VALUES(small_hlog_param_values), 246 1.1 christos }; 247 1.1 christos 248 1.1 christos static param_value_t const small_clog_param_values[] = { 249 1.1 christos {.param = ZSTD_c_chainLog, .value = 6}, 250 1.1 christos {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt}, 251 1.1 christos }; 252 1.1 christos 253 1.1 christos static config_t small_clog = { 254 1.1 christos .name = "small chain log", 255 1.1 christos .cli_args = "--zstd=clog=6,strat=7", 256 1.1 christos .param_values = PARAM_VALUES(small_clog_param_values), 257 1.1 christos }; 258 1.1 christos 259 1.1 christos static param_value_t const uncompressed_literals_param_values[] = { 260 1.1 christos {.param = ZSTD_c_compressionLevel, .value = 3}, 261 1.1 christos {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable}, 262 1.1 christos }; 263 1.1 christos 264 1.1 christos static config_t uncompressed_literals = { 265 1.1 christos .name = "uncompressed literals", 266 1.1 christos .cli_args = "-3 --no-compress-literals", 267 1.1 christos .param_values = PARAM_VALUES(uncompressed_literals_param_values), 268 1.1 christos }; 269 1.1 christos 270 1.1 christos static param_value_t const uncompressed_literals_opt_param_values[] = { 271 1.1 christos {.param = ZSTD_c_compressionLevel, .value = 19}, 272 1.1 christos {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable}, 273 1.1 christos }; 274 1.1 christos 275 1.1 christos static config_t uncompressed_literals_opt = { 276 1.1 christos .name = "uncompressed literals optimal", 277 1.1 christos .cli_args = "-19 --no-compress-literals", 278 1.1 christos .param_values = PARAM_VALUES(uncompressed_literals_opt_param_values), 279 1.1 christos }; 280 1.1 christos 281 1.1 christos static param_value_t const huffman_literals_param_values[] = { 282 1.1 christos {.param = ZSTD_c_compressionLevel, .value = -1}, 283 1.1 christos {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_enable}, 284 1.1 christos }; 285 1.1 christos 286 1.1 christos static config_t huffman_literals = { 287 1.1 christos .name = "huffman literals", 288 1.1 christos .cli_args = "--fast=1 --compress-literals", 289 1.1 christos .param_values = PARAM_VALUES(huffman_literals_param_values), 290 1.1 christos }; 291 1.1 christos 292 1.1 christos static param_value_t const explicit_params_param_values[] = { 293 1.1 christos {.param = ZSTD_c_checksumFlag, .value = 1}, 294 1.1 christos {.param = ZSTD_c_contentSizeFlag, .value = 0}, 295 1.1 christos {.param = ZSTD_c_dictIDFlag, .value = 0}, 296 1.1 christos {.param = ZSTD_c_strategy, .value = (int)ZSTD_greedy}, 297 1.1 christos {.param = ZSTD_c_windowLog, .value = 18}, 298 1.1 christos {.param = ZSTD_c_hashLog, .value = 21}, 299 1.1 christos {.param = ZSTD_c_chainLog, .value = 21}, 300 1.1 christos {.param = ZSTD_c_targetLength, .value = 100}, 301 1.1 christos }; 302 1.1 christos 303 1.1 christos static config_t explicit_params = { 304 1.1 christos .name = "explicit params", 305 1.1 christos .cli_args = "--no-check --no-dictID --zstd=strategy=3,wlog=18,hlog=21,clog=21,tlen=100", 306 1.1 christos .param_values = PARAM_VALUES(explicit_params_param_values), 307 1.1 christos }; 308 1.1 christos 309 1.1 christos static config_t const* g_configs[] = { 310 1.1 christos 311 1.1 christos #define FAST_LEVEL(x) &level_fast##x, &level_fast##x##_dict, 312 1.1 christos #define LEVEL(x) &level_##x, &level_##x##_dict, &level_##x##_dict_dms, &level_##x##_dict_dds, &level_##x##_dict_copy, &level_##x##_dict_load, 313 1.1 christos #define ROW_LEVEL(x, y) &row_##y##_level_##x, &row_##y##_level_##x##_dict_dms, &row_##y##_level_##x##_dict_dds, &row_##y##_level_##x##_dict_copy, &row_##y##_level_##x##_dict_load, 314 1.1 christos #include "levels.h" 315 1.1 christos #undef ROW_LEVEL 316 1.1 christos #undef LEVEL 317 1.1 christos #undef FAST_LEVEL 318 1.1 christos 319 1.1 christos &no_pledged_src_size, 320 1.1 christos &no_pledged_src_size_with_dict, 321 1.1 christos &ldm, 322 1.1 christos &mt, 323 1.1 christos &mt_ldm, 324 1.1 christos &small_wlog, 325 1.1 christos &small_hlog, 326 1.1 christos &small_clog, 327 1.1 christos &explicit_params, 328 1.1 christos &uncompressed_literals, 329 1.1 christos &uncompressed_literals_opt, 330 1.1 christos &huffman_literals, 331 1.1 christos &mt_advanced, 332 1.1 christos NULL, 333 1.1 christos }; 334 1.1 christos 335 1.1 christos config_t const* const* configs = g_configs; 336 1.1 christos 337 1.1 christos int config_skip_data(config_t const* config, data_t const* data) { 338 1.1 christos return config->use_dictionary && !data_has_dict(data); 339 1.1 christos } 340 1.1 christos 341 1.1 christos int config_get_level(config_t const* config) 342 1.1 christos { 343 1.1 christos param_values_t const params = config->param_values; 344 1.1 christos size_t i; 345 1.1 christos for (i = 0; i < params.size; ++i) { 346 1.1 christos if (params.data[i].param == ZSTD_c_compressionLevel) 347 1.1 christos return (int)params.data[i].value; 348 1.1 christos } 349 1.1 christos return CONFIG_NO_LEVEL; 350 1.1 christos } 351 1.1 christos 352 1.1 christos ZSTD_parameters config_get_zstd_params( 353 1.1 christos config_t const* config, 354 1.1 christos uint64_t srcSize, 355 1.1 christos size_t dictSize) 356 1.1 christos { 357 1.1 christos ZSTD_parameters zparams = {}; 358 1.1 christos param_values_t const params = config->param_values; 359 1.1 christos int level = config_get_level(config); 360 1.1 christos if (level == CONFIG_NO_LEVEL) 361 1.1 christos level = 3; 362 1.1 christos zparams = ZSTD_getParams( 363 1.1 christos level, 364 1.1 christos config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : srcSize, 365 1.1 christos dictSize); 366 1.1 christos for (size_t i = 0; i < params.size; ++i) { 367 1.1 christos unsigned const value = params.data[i].value; 368 1.1 christos switch (params.data[i].param) { 369 1.1 christos case ZSTD_c_contentSizeFlag: 370 1.1 christos zparams.fParams.contentSizeFlag = value; 371 1.1 christos break; 372 1.1 christos case ZSTD_c_checksumFlag: 373 1.1 christos zparams.fParams.checksumFlag = value; 374 1.1 christos break; 375 1.1 christos case ZSTD_c_dictIDFlag: 376 1.1 christos zparams.fParams.noDictIDFlag = !value; 377 1.1 christos break; 378 1.1 christos case ZSTD_c_windowLog: 379 1.1 christos zparams.cParams.windowLog = value; 380 1.1 christos break; 381 1.1 christos case ZSTD_c_chainLog: 382 1.1 christos zparams.cParams.chainLog = value; 383 1.1 christos break; 384 1.1 christos case ZSTD_c_hashLog: 385 1.1 christos zparams.cParams.hashLog = value; 386 1.1 christos break; 387 1.1 christos case ZSTD_c_searchLog: 388 1.1 christos zparams.cParams.searchLog = value; 389 1.1 christos break; 390 1.1 christos case ZSTD_c_minMatch: 391 1.1 christos zparams.cParams.minMatch = value; 392 1.1 christos break; 393 1.1 christos case ZSTD_c_targetLength: 394 1.1 christos zparams.cParams.targetLength = value; 395 1.1 christos break; 396 1.1 christos case ZSTD_c_strategy: 397 1.1 christos zparams.cParams.strategy = (ZSTD_strategy)value; 398 1.1 christos break; 399 1.1 christos default: 400 1.1 christos break; 401 1.1 christos } 402 1.1 christos } 403 1.1 christos return zparams; 404 1.1 christos } 405