1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos /* ************************************** 12*3117ece4Schristos * Tuning parameters 13*3117ece4Schristos ****************************************/ 14*3117ece4Schristos #ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */ 15*3117ece4Schristos # define BMK_TIMETEST_DEFAULT_S 3 16*3117ece4Schristos #endif 17*3117ece4Schristos 18*3117ece4Schristos /* ************************************* 19*3117ece4Schristos * Includes 20*3117ece4Schristos ***************************************/ 21*3117ece4Schristos /* this must be included first */ 22*3117ece4Schristos #include "platform.h" /* Large Files support, compiler specifics */ 23*3117ece4Schristos 24*3117ece4Schristos /* then following system includes */ 25*3117ece4Schristos #include <assert.h> /* assert */ 26*3117ece4Schristos #include <errno.h> 27*3117ece4Schristos #include <stdio.h> /* fprintf, fopen */ 28*3117ece4Schristos #include <stdlib.h> /* malloc, free */ 29*3117ece4Schristos #include <string.h> /* memset, strerror */ 30*3117ece4Schristos #include "util.h" /* UTIL_getFileSize, UTIL_sleep */ 31*3117ece4Schristos #include "../lib/common/mem.h" 32*3117ece4Schristos #include "benchfn.h" 33*3117ece4Schristos #include "timefn.h" /* UTIL_time_t */ 34*3117ece4Schristos #ifndef ZSTD_STATIC_LINKING_ONLY 35*3117ece4Schristos # define ZSTD_STATIC_LINKING_ONLY 36*3117ece4Schristos #endif 37*3117ece4Schristos #include "../lib/zstd.h" 38*3117ece4Schristos #include "datagen.h" /* RDG_genBuffer */ 39*3117ece4Schristos #include "lorem.h" /* LOREM_genBuffer */ 40*3117ece4Schristos #ifndef XXH_INLINE_ALL 41*3117ece4Schristos # define XXH_INLINE_ALL 42*3117ece4Schristos #endif 43*3117ece4Schristos #include "../lib/common/xxhash.h" 44*3117ece4Schristos #include "../lib/zstd_errors.h" 45*3117ece4Schristos #include "benchzstd.h" 46*3117ece4Schristos 47*3117ece4Schristos /* ************************************* 48*3117ece4Schristos * Constants 49*3117ece4Schristos ***************************************/ 50*3117ece4Schristos #ifndef ZSTD_GIT_COMMIT 51*3117ece4Schristos # define ZSTD_GIT_COMMIT_STRING "" 52*3117ece4Schristos #else 53*3117ece4Schristos # define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT) 54*3117ece4Schristos #endif 55*3117ece4Schristos 56*3117ece4Schristos #define TIMELOOP_MICROSEC (1 * 1000000ULL) /* 1 second */ 57*3117ece4Schristos #define TIMELOOP_NANOSEC (1 * 1000000000ULL) /* 1 second */ 58*3117ece4Schristos #define ACTIVEPERIOD_MICROSEC (70 * TIMELOOP_MICROSEC) /* 70 seconds */ 59*3117ece4Schristos #define COOLPERIOD_SEC 10 60*3117ece4Schristos 61*3117ece4Schristos #define KB *(1 << 10) 62*3117ece4Schristos #define MB *(1 << 20) 63*3117ece4Schristos #define GB *(1U << 30) 64*3117ece4Schristos 65*3117ece4Schristos #define BMK_RUNTEST_DEFAULT_MS 1000 66*3117ece4Schristos 67*3117ece4Schristos static const size_t maxMemory = (sizeof(size_t) == 4) 68*3117ece4Schristos ? 69*3117ece4Schristos /* 32-bit */ (2 GB - 64 MB) 70*3117ece4Schristos : 71*3117ece4Schristos /* 64-bit */ (size_t)(1ULL << ((sizeof(size_t) * 8) - 31)); 72*3117ece4Schristos 73*3117ece4Schristos /* ************************************* 74*3117ece4Schristos * console display 75*3117ece4Schristos ***************************************/ 76*3117ece4Schristos #define DISPLAY(...) \ 77*3117ece4Schristos { \ 78*3117ece4Schristos fprintf(stderr, __VA_ARGS__); \ 79*3117ece4Schristos fflush(NULL); \ 80*3117ece4Schristos } 81*3117ece4Schristos #define DISPLAYLEVEL(l, ...) \ 82*3117ece4Schristos if (displayLevel >= l) { \ 83*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 84*3117ece4Schristos } 85*3117ece4Schristos /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + 86*3117ece4Schristos * progression; 4 : + information */ 87*3117ece4Schristos #define OUTPUT(...) \ 88*3117ece4Schristos { \ 89*3117ece4Schristos fprintf(stdout, __VA_ARGS__); \ 90*3117ece4Schristos fflush(NULL); \ 91*3117ece4Schristos } 92*3117ece4Schristos #define OUTPUTLEVEL(l, ...) \ 93*3117ece4Schristos if (displayLevel >= l) { \ 94*3117ece4Schristos OUTPUT(__VA_ARGS__); \ 95*3117ece4Schristos } 96*3117ece4Schristos 97*3117ece4Schristos /* ************************************* 98*3117ece4Schristos * Exceptions 99*3117ece4Schristos ***************************************/ 100*3117ece4Schristos #ifndef DEBUG 101*3117ece4Schristos # define DEBUG 0 102*3117ece4Schristos #endif 103*3117ece4Schristos #define DEBUGOUTPUT(...) \ 104*3117ece4Schristos { \ 105*3117ece4Schristos if (DEBUG) \ 106*3117ece4Schristos DISPLAY(__VA_ARGS__); \ 107*3117ece4Schristos } 108*3117ece4Schristos 109*3117ece4Schristos #define RETURN_ERROR_INT(errorNum, ...) \ 110*3117ece4Schristos { \ 111*3117ece4Schristos DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 112*3117ece4Schristos DISPLAYLEVEL(1, "Error %i : ", errorNum); \ 113*3117ece4Schristos DISPLAYLEVEL(1, __VA_ARGS__); \ 114*3117ece4Schristos DISPLAYLEVEL(1, " \n"); \ 115*3117ece4Schristos return errorNum; \ 116*3117ece4Schristos } 117*3117ece4Schristos 118*3117ece4Schristos #define CHECK_Z(zf) \ 119*3117ece4Schristos { \ 120*3117ece4Schristos size_t const zerr = zf; \ 121*3117ece4Schristos if (ZSTD_isError(zerr)) { \ 122*3117ece4Schristos DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 123*3117ece4Schristos DISPLAY("Error : "); \ 124*3117ece4Schristos DISPLAY("%s failed : %s", #zf, ZSTD_getErrorName(zerr)); \ 125*3117ece4Schristos DISPLAY(" \n"); \ 126*3117ece4Schristos exit(1); \ 127*3117ece4Schristos } \ 128*3117ece4Schristos } 129*3117ece4Schristos 130*3117ece4Schristos #define RETURN_ERROR(errorNum, retType, ...) \ 131*3117ece4Schristos { \ 132*3117ece4Schristos retType r; \ 133*3117ece4Schristos memset(&r, 0, sizeof(retType)); \ 134*3117ece4Schristos DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 135*3117ece4Schristos DISPLAYLEVEL(1, "Error %i : ", errorNum); \ 136*3117ece4Schristos DISPLAYLEVEL(1, __VA_ARGS__); \ 137*3117ece4Schristos DISPLAYLEVEL(1, " \n"); \ 138*3117ece4Schristos r.tag = errorNum; \ 139*3117ece4Schristos return r; \ 140*3117ece4Schristos } 141*3117ece4Schristos 142*3117ece4Schristos /* replacement for snprintf(), which is not supported by C89 143*3117ece4Schristos * sprintf() would be the supported one, but it's labelled unsafe, 144*3117ece4Schristos * so some modern static analyzer will flag it as such, making it unusable. 145*3117ece4Schristos * formatString_u() replaces snprintf() for the specific case where there are only %u arguments */ 146*3117ece4Schristos static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value) 147*3117ece4Schristos { 148*3117ece4Schristos size_t written = 0; 149*3117ece4Schristos int i; 150*3117ece4Schristos assert(value <= 100); 151*3117ece4Schristos 152*3117ece4Schristos for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; ++i) { 153*3117ece4Schristos if (formatString[i] != '%') { 154*3117ece4Schristos buffer[written++] = formatString[i]; 155*3117ece4Schristos continue; 156*3117ece4Schristos } 157*3117ece4Schristos 158*3117ece4Schristos if (formatString[++i] == 'u') { 159*3117ece4Schristos /* Handle single digit */ 160*3117ece4Schristos if (value < 10) { 161*3117ece4Schristos buffer[written++] = '0' + (char)value; 162*3117ece4Schristos } else if (value < 100) { 163*3117ece4Schristos /* Handle two digits */ 164*3117ece4Schristos if (written >= buffer_size - 2) { 165*3117ece4Schristos return -1; /* buffer overflow */ 166*3117ece4Schristos } 167*3117ece4Schristos buffer[written++] = '0' + (char)(value / 10); 168*3117ece4Schristos buffer[written++] = '0' + (char)(value % 10); 169*3117ece4Schristos } else { /* 100 */ 170*3117ece4Schristos if (written >= buffer_size - 3) { 171*3117ece4Schristos return -1; /* buffer overflow */ 172*3117ece4Schristos } 173*3117ece4Schristos buffer[written++] = '1'; 174*3117ece4Schristos buffer[written++] = '0'; 175*3117ece4Schristos buffer[written++] = '0'; 176*3117ece4Schristos } 177*3117ece4Schristos } else if (formatString[i] == '%') { /* Check for escaped percent sign */ 178*3117ece4Schristos buffer[written++] = '%'; 179*3117ece4Schristos } else { 180*3117ece4Schristos return -1; /* unsupported format */ 181*3117ece4Schristos } 182*3117ece4Schristos } 183*3117ece4Schristos 184*3117ece4Schristos if (written < buffer_size) { 185*3117ece4Schristos buffer[written] = '\0'; 186*3117ece4Schristos } else { 187*3117ece4Schristos buffer[0] = '\0'; /* Handle truncation */ 188*3117ece4Schristos } 189*3117ece4Schristos 190*3117ece4Schristos return (int)written; 191*3117ece4Schristos } 192*3117ece4Schristos 193*3117ece4Schristos /* ************************************* 194*3117ece4Schristos * Benchmark Parameters 195*3117ece4Schristos ***************************************/ 196*3117ece4Schristos 197*3117ece4Schristos BMK_advancedParams_t BMK_initAdvancedParams(void) 198*3117ece4Schristos { 199*3117ece4Schristos BMK_advancedParams_t const res = { 200*3117ece4Schristos BMK_both, /* mode */ 201*3117ece4Schristos BMK_TIMETEST_DEFAULT_S, /* nbSeconds */ 202*3117ece4Schristos 0, /* blockSize */ 203*3117ece4Schristos 0, /* targetCBlockSize */ 204*3117ece4Schristos 0, /* nbWorkers */ 205*3117ece4Schristos 0, /* realTime */ 206*3117ece4Schristos 0, /* additionalParam */ 207*3117ece4Schristos 0, /* ldmFlag */ 208*3117ece4Schristos 0, /* ldmMinMatch */ 209*3117ece4Schristos 0, /* ldmHashLog */ 210*3117ece4Schristos 0, /* ldmBuckSizeLog */ 211*3117ece4Schristos 0, /* ldmHashRateLog */ 212*3117ece4Schristos ZSTD_ps_auto, /* literalCompressionMode */ 213*3117ece4Schristos 0 /* useRowMatchFinder */ 214*3117ece4Schristos }; 215*3117ece4Schristos return res; 216*3117ece4Schristos } 217*3117ece4Schristos 218*3117ece4Schristos /* ******************************************************** 219*3117ece4Schristos * Bench functions 220*3117ece4Schristos **********************************************************/ 221*3117ece4Schristos typedef struct { 222*3117ece4Schristos const void* srcPtr; 223*3117ece4Schristos size_t srcSize; 224*3117ece4Schristos void* cPtr; 225*3117ece4Schristos size_t cRoom; 226*3117ece4Schristos size_t cSize; 227*3117ece4Schristos void* resPtr; 228*3117ece4Schristos size_t resSize; 229*3117ece4Schristos } blockParam_t; 230*3117ece4Schristos 231*3117ece4Schristos #undef MIN 232*3117ece4Schristos #undef MAX 233*3117ece4Schristos #define MIN(a, b) ((a) < (b) ? (a) : (b)) 234*3117ece4Schristos #define MAX(a, b) ((a) > (b) ? (a) : (b)) 235*3117ece4Schristos 236*3117ece4Schristos static void BMK_initCCtx( 237*3117ece4Schristos ZSTD_CCtx* ctx, 238*3117ece4Schristos const void* dictBuffer, 239*3117ece4Schristos size_t dictBufferSize, 240*3117ece4Schristos int cLevel, 241*3117ece4Schristos const ZSTD_compressionParameters* comprParams, 242*3117ece4Schristos const BMK_advancedParams_t* adv) 243*3117ece4Schristos { 244*3117ece4Schristos ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters); 245*3117ece4Schristos if (adv->nbWorkers == 1) { 246*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0)); 247*3117ece4Schristos } else { 248*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers)); 249*3117ece4Schristos } 250*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel)); 251*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 252*3117ece4Schristos ctx, ZSTD_c_useRowMatchFinder, adv->useRowMatchFinder)); 253*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 254*3117ece4Schristos ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag)); 255*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch)); 256*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog)); 257*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 258*3117ece4Schristos ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog)); 259*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 260*3117ece4Schristos ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog)); 261*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 262*3117ece4Schristos ctx, ZSTD_c_windowLog, (int)comprParams->windowLog)); 263*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 264*3117ece4Schristos ctx, ZSTD_c_hashLog, (int)comprParams->hashLog)); 265*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 266*3117ece4Schristos ctx, ZSTD_c_chainLog, (int)comprParams->chainLog)); 267*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 268*3117ece4Schristos ctx, ZSTD_c_searchLog, (int)comprParams->searchLog)); 269*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 270*3117ece4Schristos ctx, ZSTD_c_minMatch, (int)comprParams->minMatch)); 271*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 272*3117ece4Schristos ctx, ZSTD_c_targetLength, (int)comprParams->targetLength)); 273*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 274*3117ece4Schristos ctx, 275*3117ece4Schristos ZSTD_c_literalCompressionMode, 276*3117ece4Schristos (int)adv->literalCompressionMode)); 277*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 278*3117ece4Schristos ctx, ZSTD_c_strategy, (int)comprParams->strategy)); 279*3117ece4Schristos CHECK_Z(ZSTD_CCtx_setParameter( 280*3117ece4Schristos ctx, ZSTD_c_targetCBlockSize, (int)adv->targetCBlockSize)); 281*3117ece4Schristos CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize)); 282*3117ece4Schristos } 283*3117ece4Schristos 284*3117ece4Schristos static void 285*3117ece4Schristos BMK_initDCtx(ZSTD_DCtx* dctx, const void* dictBuffer, size_t dictBufferSize) 286*3117ece4Schristos { 287*3117ece4Schristos CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters)); 288*3117ece4Schristos CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize)); 289*3117ece4Schristos } 290*3117ece4Schristos 291*3117ece4Schristos typedef struct { 292*3117ece4Schristos ZSTD_CCtx* cctx; 293*3117ece4Schristos const void* dictBuffer; 294*3117ece4Schristos size_t dictBufferSize; 295*3117ece4Schristos int cLevel; 296*3117ece4Schristos const ZSTD_compressionParameters* comprParams; 297*3117ece4Schristos const BMK_advancedParams_t* adv; 298*3117ece4Schristos } BMK_initCCtxArgs; 299*3117ece4Schristos 300*3117ece4Schristos static size_t local_initCCtx(void* payload) 301*3117ece4Schristos { 302*3117ece4Schristos BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload; 303*3117ece4Schristos BMK_initCCtx( 304*3117ece4Schristos ag->cctx, 305*3117ece4Schristos ag->dictBuffer, 306*3117ece4Schristos ag->dictBufferSize, 307*3117ece4Schristos ag->cLevel, 308*3117ece4Schristos ag->comprParams, 309*3117ece4Schristos ag->adv); 310*3117ece4Schristos return 0; 311*3117ece4Schristos } 312*3117ece4Schristos 313*3117ece4Schristos typedef struct { 314*3117ece4Schristos ZSTD_DCtx* dctx; 315*3117ece4Schristos const void* dictBuffer; 316*3117ece4Schristos size_t dictBufferSize; 317*3117ece4Schristos } BMK_initDCtxArgs; 318*3117ece4Schristos 319*3117ece4Schristos static size_t local_initDCtx(void* payload) 320*3117ece4Schristos { 321*3117ece4Schristos BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload; 322*3117ece4Schristos BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize); 323*3117ece4Schristos return 0; 324*3117ece4Schristos } 325*3117ece4Schristos 326*3117ece4Schristos /* `addArgs` is the context */ 327*3117ece4Schristos static size_t local_defaultCompress( 328*3117ece4Schristos const void* srcBuffer, 329*3117ece4Schristos size_t srcSize, 330*3117ece4Schristos void* dstBuffer, 331*3117ece4Schristos size_t dstSize, 332*3117ece4Schristos void* addArgs) 333*3117ece4Schristos { 334*3117ece4Schristos ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs; 335*3117ece4Schristos return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize); 336*3117ece4Schristos } 337*3117ece4Schristos 338*3117ece4Schristos /* `addArgs` is the context */ 339*3117ece4Schristos static size_t local_defaultDecompress( 340*3117ece4Schristos const void* srcBuffer, 341*3117ece4Schristos size_t srcSize, 342*3117ece4Schristos void* dstBuffer, 343*3117ece4Schristos size_t dstCapacity, 344*3117ece4Schristos void* addArgs) 345*3117ece4Schristos { 346*3117ece4Schristos size_t moreToFlush = 1; 347*3117ece4Schristos ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs; 348*3117ece4Schristos ZSTD_inBuffer in; 349*3117ece4Schristos ZSTD_outBuffer out; 350*3117ece4Schristos in.src = srcBuffer; 351*3117ece4Schristos in.size = srcSize; 352*3117ece4Schristos in.pos = 0; 353*3117ece4Schristos out.dst = dstBuffer; 354*3117ece4Schristos out.size = dstCapacity; 355*3117ece4Schristos out.pos = 0; 356*3117ece4Schristos while (moreToFlush) { 357*3117ece4Schristos if (out.pos == out.size) { 358*3117ece4Schristos return (size_t)-ZSTD_error_dstSize_tooSmall; 359*3117ece4Schristos } 360*3117ece4Schristos moreToFlush = ZSTD_decompressStream(dctx, &out, &in); 361*3117ece4Schristos if (ZSTD_isError(moreToFlush)) { 362*3117ece4Schristos return moreToFlush; 363*3117ece4Schristos } 364*3117ece4Schristos } 365*3117ece4Schristos return out.pos; 366*3117ece4Schristos } 367*3117ece4Schristos 368*3117ece4Schristos /* ================================================================= */ 369*3117ece4Schristos /* Benchmark Zstandard, mem-to-mem scenarios */ 370*3117ece4Schristos /* ================================================================= */ 371*3117ece4Schristos 372*3117ece4Schristos int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome) 373*3117ece4Schristos { 374*3117ece4Schristos return outcome.tag == 0; 375*3117ece4Schristos } 376*3117ece4Schristos 377*3117ece4Schristos BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome) 378*3117ece4Schristos { 379*3117ece4Schristos assert(outcome.tag == 0); 380*3117ece4Schristos return outcome.internal_never_use_directly; 381*3117ece4Schristos } 382*3117ece4Schristos 383*3117ece4Schristos static BMK_benchOutcome_t BMK_benchOutcome_error(void) 384*3117ece4Schristos { 385*3117ece4Schristos BMK_benchOutcome_t b; 386*3117ece4Schristos memset(&b, 0, sizeof(b)); 387*3117ece4Schristos b.tag = 1; 388*3117ece4Schristos return b; 389*3117ece4Schristos } 390*3117ece4Schristos 391*3117ece4Schristos static BMK_benchOutcome_t BMK_benchOutcome_setValidResult( 392*3117ece4Schristos BMK_benchResult_t result) 393*3117ece4Schristos { 394*3117ece4Schristos BMK_benchOutcome_t b; 395*3117ece4Schristos b.tag = 0; 396*3117ece4Schristos b.internal_never_use_directly = result; 397*3117ece4Schristos return b; 398*3117ece4Schristos } 399*3117ece4Schristos 400*3117ece4Schristos /* benchMem with no allocation */ 401*3117ece4Schristos static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc( 402*3117ece4Schristos const void** srcPtrs, 403*3117ece4Schristos size_t* srcSizes, 404*3117ece4Schristos void** cPtrs, 405*3117ece4Schristos size_t* cCapacities, 406*3117ece4Schristos size_t* cSizes, 407*3117ece4Schristos void** resPtrs, 408*3117ece4Schristos size_t* resSizes, 409*3117ece4Schristos void** resultBufferPtr, 410*3117ece4Schristos void* compressedBuffer, 411*3117ece4Schristos size_t maxCompressedSize, 412*3117ece4Schristos BMK_timedFnState_t* timeStateCompress, 413*3117ece4Schristos BMK_timedFnState_t* timeStateDecompress, 414*3117ece4Schristos 415*3117ece4Schristos const void* srcBuffer, 416*3117ece4Schristos size_t srcSize, 417*3117ece4Schristos const size_t* fileSizes, 418*3117ece4Schristos unsigned nbFiles, 419*3117ece4Schristos const int cLevel, 420*3117ece4Schristos const ZSTD_compressionParameters* comprParams, 421*3117ece4Schristos const void* dictBuffer, 422*3117ece4Schristos size_t dictBufferSize, 423*3117ece4Schristos ZSTD_CCtx* cctx, 424*3117ece4Schristos ZSTD_DCtx* dctx, 425*3117ece4Schristos int displayLevel, 426*3117ece4Schristos const char* displayName, 427*3117ece4Schristos const BMK_advancedParams_t* adv) 428*3117ece4Schristos { 429*3117ece4Schristos size_t const blockSize = 430*3117ece4Schristos ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly)) 431*3117ece4Schristos ? adv->blockSize 432*3117ece4Schristos : srcSize) 433*3117ece4Schristos + (!srcSize); /* avoid div by 0 */ 434*3117ece4Schristos BMK_benchResult_t benchResult; 435*3117ece4Schristos size_t const loadedCompressedSize = srcSize; 436*3117ece4Schristos size_t cSize = 0; 437*3117ece4Schristos double ratio = 0.; 438*3117ece4Schristos U32 nbBlocks; 439*3117ece4Schristos 440*3117ece4Schristos assert(cctx != NULL); 441*3117ece4Schristos assert(dctx != NULL); 442*3117ece4Schristos 443*3117ece4Schristos /* init */ 444*3117ece4Schristos memset(&benchResult, 0, sizeof(benchResult)); 445*3117ece4Schristos if (strlen(displayName) > 17) 446*3117ece4Schristos displayName += 447*3117ece4Schristos strlen(displayName) - 17; /* display last 17 characters */ 448*3117ece4Schristos if (adv->mode == BMK_decodeOnly) { 449*3117ece4Schristos /* benchmark only decompression : source must be already compressed */ 450*3117ece4Schristos const char* srcPtr = (const char*)srcBuffer; 451*3117ece4Schristos U64 totalDSize64 = 0; 452*3117ece4Schristos U32 fileNb; 453*3117ece4Schristos for (fileNb = 0; fileNb < nbFiles; fileNb++) { 454*3117ece4Schristos U64 const fSize64 = 455*3117ece4Schristos ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]); 456*3117ece4Schristos if (fSize64 == ZSTD_CONTENTSIZE_UNKNOWN) { 457*3117ece4Schristos RETURN_ERROR( 458*3117ece4Schristos 32, 459*3117ece4Schristos BMK_benchOutcome_t, 460*3117ece4Schristos "Decompressed size cannot be determined: cannot benchmark"); 461*3117ece4Schristos } 462*3117ece4Schristos if (fSize64 == ZSTD_CONTENTSIZE_ERROR) { 463*3117ece4Schristos RETURN_ERROR( 464*3117ece4Schristos 32, 465*3117ece4Schristos BMK_benchOutcome_t, 466*3117ece4Schristos "Error while trying to assess decompressed size: data may be invalid"); 467*3117ece4Schristos } 468*3117ece4Schristos totalDSize64 += fSize64; 469*3117ece4Schristos srcPtr += fileSizes[fileNb]; 470*3117ece4Schristos } 471*3117ece4Schristos { 472*3117ece4Schristos size_t const decodedSize = (size_t)totalDSize64; 473*3117ece4Schristos assert((U64)decodedSize == totalDSize64); /* check overflow */ 474*3117ece4Schristos free(*resultBufferPtr); 475*3117ece4Schristos if (totalDSize64 > decodedSize) { /* size_t overflow */ 476*3117ece4Schristos RETURN_ERROR( 477*3117ece4Schristos 32, 478*3117ece4Schristos BMK_benchOutcome_t, 479*3117ece4Schristos "decompressed size is too large for local system"); 480*3117ece4Schristos } 481*3117ece4Schristos *resultBufferPtr = malloc(decodedSize); 482*3117ece4Schristos if (!(*resultBufferPtr)) { 483*3117ece4Schristos RETURN_ERROR( 484*3117ece4Schristos 33, 485*3117ece4Schristos BMK_benchOutcome_t, 486*3117ece4Schristos "allocation error: not enough memory"); 487*3117ece4Schristos } 488*3117ece4Schristos cSize = srcSize; 489*3117ece4Schristos srcSize = decodedSize; 490*3117ece4Schristos ratio = (double)srcSize / (double)cSize; 491*3117ece4Schristos } 492*3117ece4Schristos } 493*3117ece4Schristos 494*3117ece4Schristos /* Init data blocks */ 495*3117ece4Schristos { 496*3117ece4Schristos const char* srcPtr = (const char*)srcBuffer; 497*3117ece4Schristos char* cPtr = (char*)compressedBuffer; 498*3117ece4Schristos char* resPtr = (char*)(*resultBufferPtr); 499*3117ece4Schristos U32 fileNb; 500*3117ece4Schristos for (nbBlocks = 0, fileNb = 0; fileNb < nbFiles; fileNb++) { 501*3117ece4Schristos size_t remaining = fileSizes[fileNb]; 502*3117ece4Schristos U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly) 503*3117ece4Schristos ? 1 504*3117ece4Schristos : (U32)((remaining + (blockSize - 1)) / blockSize); 505*3117ece4Schristos U32 const blockEnd = nbBlocks + nbBlocksforThisFile; 506*3117ece4Schristos for (; nbBlocks < blockEnd; nbBlocks++) { 507*3117ece4Schristos size_t const thisBlockSize = MIN(remaining, blockSize); 508*3117ece4Schristos srcPtrs[nbBlocks] = srcPtr; 509*3117ece4Schristos srcSizes[nbBlocks] = thisBlockSize; 510*3117ece4Schristos cPtrs[nbBlocks] = cPtr; 511*3117ece4Schristos cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly) 512*3117ece4Schristos ? thisBlockSize 513*3117ece4Schristos : ZSTD_compressBound(thisBlockSize); 514*3117ece4Schristos resPtrs[nbBlocks] = resPtr; 515*3117ece4Schristos resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly) 516*3117ece4Schristos ? (size_t)ZSTD_findDecompressedSize( 517*3117ece4Schristos srcPtr, thisBlockSize) 518*3117ece4Schristos : thisBlockSize; 519*3117ece4Schristos srcPtr += thisBlockSize; 520*3117ece4Schristos cPtr += cCapacities[nbBlocks]; 521*3117ece4Schristos resPtr += thisBlockSize; 522*3117ece4Schristos remaining -= thisBlockSize; 523*3117ece4Schristos if (adv->mode == BMK_decodeOnly) { 524*3117ece4Schristos cSizes[nbBlocks] = thisBlockSize; 525*3117ece4Schristos benchResult.cSize = thisBlockSize; 526*3117ece4Schristos } 527*3117ece4Schristos } 528*3117ece4Schristos } 529*3117ece4Schristos } 530*3117ece4Schristos 531*3117ece4Schristos /* warming up `compressedBuffer` */ 532*3117ece4Schristos if (adv->mode == BMK_decodeOnly) { 533*3117ece4Schristos memcpy(compressedBuffer, srcBuffer, loadedCompressedSize); 534*3117ece4Schristos } else { 535*3117ece4Schristos RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1); 536*3117ece4Schristos } 537*3117ece4Schristos 538*3117ece4Schristos if (!UTIL_support_MT_measurements() && adv->nbWorkers > 1) { 539*3117ece4Schristos OUTPUTLEVEL( 540*3117ece4Schristos 2, 541*3117ece4Schristos "Warning : time measurements may be incorrect in multithreading mode... \n") 542*3117ece4Schristos } 543*3117ece4Schristos 544*3117ece4Schristos /* Bench */ 545*3117ece4Schristos { 546*3117ece4Schristos U64 const crcOrig = (adv->mode == BMK_decodeOnly) 547*3117ece4Schristos ? 0 548*3117ece4Schristos : XXH64(srcBuffer, srcSize, 0); 549*3117ece4Schristos #define NB_MARKS 4 550*3117ece4Schristos const char* marks[NB_MARKS] = { " |", " /", " =", " \\" }; 551*3117ece4Schristos U32 markNb = 0; 552*3117ece4Schristos int compressionCompleted = (adv->mode == BMK_decodeOnly); 553*3117ece4Schristos int decompressionCompleted = (adv->mode == BMK_compressOnly); 554*3117ece4Schristos BMK_benchParams_t cbp, dbp; 555*3117ece4Schristos BMK_initCCtxArgs cctxprep; 556*3117ece4Schristos BMK_initDCtxArgs dctxprep; 557*3117ece4Schristos 558*3117ece4Schristos cbp.benchFn = local_defaultCompress; /* ZSTD_compress2 */ 559*3117ece4Schristos cbp.benchPayload = cctx; 560*3117ece4Schristos cbp.initFn = local_initCCtx; /* BMK_initCCtx */ 561*3117ece4Schristos cbp.initPayload = &cctxprep; 562*3117ece4Schristos cbp.errorFn = ZSTD_isError; 563*3117ece4Schristos cbp.blockCount = nbBlocks; 564*3117ece4Schristos cbp.srcBuffers = srcPtrs; 565*3117ece4Schristos cbp.srcSizes = srcSizes; 566*3117ece4Schristos cbp.dstBuffers = cPtrs; 567*3117ece4Schristos cbp.dstCapacities = cCapacities; 568*3117ece4Schristos cbp.blockResults = cSizes; 569*3117ece4Schristos 570*3117ece4Schristos cctxprep.cctx = cctx; 571*3117ece4Schristos cctxprep.dictBuffer = dictBuffer; 572*3117ece4Schristos cctxprep.dictBufferSize = dictBufferSize; 573*3117ece4Schristos cctxprep.cLevel = cLevel; 574*3117ece4Schristos cctxprep.comprParams = comprParams; 575*3117ece4Schristos cctxprep.adv = adv; 576*3117ece4Schristos 577*3117ece4Schristos dbp.benchFn = local_defaultDecompress; 578*3117ece4Schristos dbp.benchPayload = dctx; 579*3117ece4Schristos dbp.initFn = local_initDCtx; 580*3117ece4Schristos dbp.initPayload = &dctxprep; 581*3117ece4Schristos dbp.errorFn = ZSTD_isError; 582*3117ece4Schristos dbp.blockCount = nbBlocks; 583*3117ece4Schristos dbp.srcBuffers = (const void* const*)cPtrs; 584*3117ece4Schristos dbp.srcSizes = cSizes; 585*3117ece4Schristos dbp.dstBuffers = resPtrs; 586*3117ece4Schristos dbp.dstCapacities = resSizes; 587*3117ece4Schristos dbp.blockResults = NULL; 588*3117ece4Schristos 589*3117ece4Schristos dctxprep.dctx = dctx; 590*3117ece4Schristos dctxprep.dictBuffer = dictBuffer; 591*3117ece4Schristos dctxprep.dictBufferSize = dictBufferSize; 592*3117ece4Schristos 593*3117ece4Schristos OUTPUTLEVEL(2, "\r%70s\r", ""); /* blank line */ 594*3117ece4Schristos assert(srcSize < UINT_MAX); 595*3117ece4Schristos OUTPUTLEVEL( 596*3117ece4Schristos 2, 597*3117ece4Schristos "%2s-%-17.17s :%10u -> \r", 598*3117ece4Schristos marks[markNb], 599*3117ece4Schristos displayName, 600*3117ece4Schristos (unsigned)srcSize); 601*3117ece4Schristos 602*3117ece4Schristos while (!(compressionCompleted && decompressionCompleted)) { 603*3117ece4Schristos if (!compressionCompleted) { 604*3117ece4Schristos BMK_runOutcome_t const cOutcome = 605*3117ece4Schristos BMK_benchTimedFn(timeStateCompress, cbp); 606*3117ece4Schristos 607*3117ece4Schristos if (!BMK_isSuccessful_runOutcome(cOutcome)) { 608*3117ece4Schristos RETURN_ERROR(30, BMK_benchOutcome_t, "compression error"); 609*3117ece4Schristos } 610*3117ece4Schristos 611*3117ece4Schristos { 612*3117ece4Schristos BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome); 613*3117ece4Schristos cSize = cResult.sumOfReturn; 614*3117ece4Schristos ratio = (double)srcSize / (double)cSize; 615*3117ece4Schristos { 616*3117ece4Schristos BMK_benchResult_t newResult; 617*3117ece4Schristos newResult.cSpeed = 618*3117ece4Schristos (U64)((double)srcSize * TIMELOOP_NANOSEC 619*3117ece4Schristos / cResult.nanoSecPerRun); 620*3117ece4Schristos benchResult.cSize = cSize; 621*3117ece4Schristos if (newResult.cSpeed > benchResult.cSpeed) 622*3117ece4Schristos benchResult.cSpeed = newResult.cSpeed; 623*3117ece4Schristos } 624*3117ece4Schristos } 625*3117ece4Schristos 626*3117ece4Schristos { 627*3117ece4Schristos int const ratioAccuracy = (ratio < 10.) ? 3 : 2; 628*3117ece4Schristos assert(cSize < UINT_MAX); 629*3117ece4Schristos OUTPUTLEVEL( 630*3117ece4Schristos 2, 631*3117ece4Schristos "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \r", 632*3117ece4Schristos marks[markNb], 633*3117ece4Schristos displayName, 634*3117ece4Schristos (unsigned)srcSize, 635*3117ece4Schristos (unsigned)cSize, 636*3117ece4Schristos ratioAccuracy, 637*3117ece4Schristos ratio, 638*3117ece4Schristos benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, 639*3117ece4Schristos (double)benchResult.cSpeed / MB_UNIT); 640*3117ece4Schristos } 641*3117ece4Schristos compressionCompleted = 642*3117ece4Schristos BMK_isCompleted_TimedFn(timeStateCompress); 643*3117ece4Schristos } 644*3117ece4Schristos 645*3117ece4Schristos if (!decompressionCompleted) { 646*3117ece4Schristos BMK_runOutcome_t const dOutcome = 647*3117ece4Schristos BMK_benchTimedFn(timeStateDecompress, dbp); 648*3117ece4Schristos 649*3117ece4Schristos if (!BMK_isSuccessful_runOutcome(dOutcome)) { 650*3117ece4Schristos RETURN_ERROR(30, BMK_benchOutcome_t, "decompression error"); 651*3117ece4Schristos } 652*3117ece4Schristos 653*3117ece4Schristos { 654*3117ece4Schristos BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome); 655*3117ece4Schristos U64 const newDSpeed = 656*3117ece4Schristos (U64)((double)srcSize * TIMELOOP_NANOSEC 657*3117ece4Schristos / dResult.nanoSecPerRun); 658*3117ece4Schristos if (newDSpeed > benchResult.dSpeed) 659*3117ece4Schristos benchResult.dSpeed = newDSpeed; 660*3117ece4Schristos } 661*3117ece4Schristos 662*3117ece4Schristos { 663*3117ece4Schristos int const ratioAccuracy = (ratio < 10.) ? 3 : 2; 664*3117ece4Schristos OUTPUTLEVEL( 665*3117ece4Schristos 2, 666*3117ece4Schristos "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r", 667*3117ece4Schristos marks[markNb], 668*3117ece4Schristos displayName, 669*3117ece4Schristos (unsigned)srcSize, 670*3117ece4Schristos (unsigned)cSize, 671*3117ece4Schristos ratioAccuracy, 672*3117ece4Schristos ratio, 673*3117ece4Schristos benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, 674*3117ece4Schristos (double)benchResult.cSpeed / MB_UNIT, 675*3117ece4Schristos (double)benchResult.dSpeed / MB_UNIT); 676*3117ece4Schristos } 677*3117ece4Schristos decompressionCompleted = 678*3117ece4Schristos BMK_isCompleted_TimedFn(timeStateDecompress); 679*3117ece4Schristos } 680*3117ece4Schristos markNb = (markNb + 1) % NB_MARKS; 681*3117ece4Schristos } /* while (!(compressionCompleted && decompressionCompleted)) */ 682*3117ece4Schristos 683*3117ece4Schristos /* CRC Checking */ 684*3117ece4Schristos { 685*3117ece4Schristos const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr); 686*3117ece4Schristos U64 const crcCheck = XXH64(resultBuffer, srcSize, 0); 687*3117ece4Schristos if ((adv->mode == BMK_both) && (crcOrig != crcCheck)) { 688*3117ece4Schristos size_t u; 689*3117ece4Schristos DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n", 690*3117ece4Schristos displayName, 691*3117ece4Schristos (unsigned)crcOrig, 692*3117ece4Schristos (unsigned)crcCheck); 693*3117ece4Schristos for (u = 0; u < srcSize; u++) { 694*3117ece4Schristos if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) { 695*3117ece4Schristos unsigned segNb, bNb, pos; 696*3117ece4Schristos size_t bacc = 0; 697*3117ece4Schristos DISPLAY("Decoding error at pos %u ", (unsigned)u); 698*3117ece4Schristos for (segNb = 0; segNb < nbBlocks; segNb++) { 699*3117ece4Schristos if (bacc + srcSizes[segNb] > u) 700*3117ece4Schristos break; 701*3117ece4Schristos bacc += srcSizes[segNb]; 702*3117ece4Schristos } 703*3117ece4Schristos pos = (U32)(u - bacc); 704*3117ece4Schristos bNb = pos / (128 KB); 705*3117ece4Schristos DISPLAY("(sample %u, block %u, pos %u) \n", 706*3117ece4Schristos segNb, 707*3117ece4Schristos bNb, 708*3117ece4Schristos pos); 709*3117ece4Schristos { 710*3117ece4Schristos size_t const lowest = (u > 5) ? 5 : u; 711*3117ece4Schristos size_t n; 712*3117ece4Schristos DISPLAY("origin: "); 713*3117ece4Schristos for (n = lowest; n > 0; n--) 714*3117ece4Schristos DISPLAY("%02X ", 715*3117ece4Schristos ((const BYTE*)srcBuffer)[u - n]); 716*3117ece4Schristos DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]); 717*3117ece4Schristos for (n = 1; n < 3; n++) 718*3117ece4Schristos DISPLAY("%02X ", 719*3117ece4Schristos ((const BYTE*)srcBuffer)[u + n]); 720*3117ece4Schristos DISPLAY(" \n"); 721*3117ece4Schristos DISPLAY("decode: "); 722*3117ece4Schristos for (n = lowest; n > 0; n--) 723*3117ece4Schristos DISPLAY("%02X ", resultBuffer[u - n]); 724*3117ece4Schristos DISPLAY(" :%02X: ", resultBuffer[u]); 725*3117ece4Schristos for (n = 1; n < 3; n++) 726*3117ece4Schristos DISPLAY("%02X ", resultBuffer[u + n]); 727*3117ece4Schristos DISPLAY(" \n"); 728*3117ece4Schristos } 729*3117ece4Schristos break; 730*3117ece4Schristos } 731*3117ece4Schristos if (u == srcSize - 1) { /* should never happen */ 732*3117ece4Schristos DISPLAY("no difference detected\n"); 733*3117ece4Schristos } 734*3117ece4Schristos } /* for (u=0; u<srcSize; u++) */ 735*3117ece4Schristos } /* if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) */ 736*3117ece4Schristos } /* CRC Checking */ 737*3117ece4Schristos 738*3117ece4Schristos if (displayLevel 739*3117ece4Schristos == 1) { /* hidden display mode -q, used by python speed benchmark */ 740*3117ece4Schristos double const cSpeed = (double)benchResult.cSpeed / MB_UNIT; 741*3117ece4Schristos double const dSpeed = (double)benchResult.dSpeed / MB_UNIT; 742*3117ece4Schristos if (adv->additionalParam) { 743*3117ece4Schristos OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s (param=%d)\n", 744*3117ece4Schristos cLevel, 745*3117ece4Schristos (int)cSize, 746*3117ece4Schristos ratio, 747*3117ece4Schristos cSpeed, 748*3117ece4Schristos dSpeed, 749*3117ece4Schristos displayName, 750*3117ece4Schristos adv->additionalParam); 751*3117ece4Schristos } else { 752*3117ece4Schristos OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n", 753*3117ece4Schristos cLevel, 754*3117ece4Schristos (int)cSize, 755*3117ece4Schristos ratio, 756*3117ece4Schristos cSpeed, 757*3117ece4Schristos dSpeed, 758*3117ece4Schristos displayName); 759*3117ece4Schristos } 760*3117ece4Schristos } 761*3117ece4Schristos 762*3117ece4Schristos OUTPUTLEVEL(2, "%2i#\n", cLevel); 763*3117ece4Schristos } /* Bench */ 764*3117ece4Schristos 765*3117ece4Schristos benchResult.cMem = 766*3117ece4Schristos (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx); 767*3117ece4Schristos return BMK_benchOutcome_setValidResult(benchResult); 768*3117ece4Schristos } 769*3117ece4Schristos 770*3117ece4Schristos BMK_benchOutcome_t BMK_benchMemAdvanced( 771*3117ece4Schristos const void* srcBuffer, 772*3117ece4Schristos size_t srcSize, 773*3117ece4Schristos void* dstBuffer, 774*3117ece4Schristos size_t dstCapacity, 775*3117ece4Schristos const size_t* fileSizes, 776*3117ece4Schristos unsigned nbFiles, 777*3117ece4Schristos int cLevel, 778*3117ece4Schristos const ZSTD_compressionParameters* comprParams, 779*3117ece4Schristos const void* dictBuffer, 780*3117ece4Schristos size_t dictBufferSize, 781*3117ece4Schristos int displayLevel, 782*3117ece4Schristos const char* displayName, 783*3117ece4Schristos const BMK_advancedParams_t* adv) 784*3117ece4Schristos 785*3117ece4Schristos { 786*3117ece4Schristos int const dstParamsError = 787*3117ece4Schristos !dstBuffer ^ !dstCapacity; /* must be both NULL or none */ 788*3117ece4Schristos 789*3117ece4Schristos size_t const blockSize = 790*3117ece4Schristos ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly)) 791*3117ece4Schristos ? adv->blockSize 792*3117ece4Schristos : srcSize) 793*3117ece4Schristos + (!srcSize) /* avoid div by 0 */; 794*3117ece4Schristos U32 const maxNbBlocks = 795*3117ece4Schristos (U32)((srcSize + (blockSize - 1)) / blockSize) + nbFiles; 796*3117ece4Schristos 797*3117ece4Schristos /* these are the blockTable parameters, just split up */ 798*3117ece4Schristos const void** const srcPtrs = 799*3117ece4Schristos (const void**)malloc(maxNbBlocks * sizeof(void*)); 800*3117ece4Schristos size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 801*3117ece4Schristos 802*3117ece4Schristos void** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*)); 803*3117ece4Schristos size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 804*3117ece4Schristos size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 805*3117ece4Schristos 806*3117ece4Schristos void** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*)); 807*3117ece4Schristos size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 808*3117ece4Schristos 809*3117ece4Schristos BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState( 810*3117ece4Schristos adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS); 811*3117ece4Schristos BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState( 812*3117ece4Schristos adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS); 813*3117ece4Schristos 814*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 815*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 816*3117ece4Schristos 817*3117ece4Schristos const size_t maxCompressedSize = dstCapacity 818*3117ece4Schristos ? dstCapacity 819*3117ece4Schristos : ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); 820*3117ece4Schristos 821*3117ece4Schristos void* const internalDstBuffer = 822*3117ece4Schristos dstBuffer ? NULL : malloc(maxCompressedSize); 823*3117ece4Schristos void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer; 824*3117ece4Schristos 825*3117ece4Schristos BMK_benchOutcome_t outcome = 826*3117ece4Schristos BMK_benchOutcome_error(); /* error by default */ 827*3117ece4Schristos 828*3117ece4Schristos void* resultBuffer = srcSize ? malloc(srcSize) : NULL; 829*3117ece4Schristos 830*3117ece4Schristos int const allocationincomplete = !srcPtrs || !srcSizes || !cPtrs || !cSizes 831*3117ece4Schristos || !cCapacities || !resPtrs || !resSizes || !timeStateCompress 832*3117ece4Schristos || !timeStateDecompress || !cctx || !dctx || !compressedBuffer 833*3117ece4Schristos || !resultBuffer; 834*3117ece4Schristos 835*3117ece4Schristos if (!allocationincomplete && !dstParamsError) { 836*3117ece4Schristos outcome = BMK_benchMemAdvancedNoAlloc( 837*3117ece4Schristos srcPtrs, 838*3117ece4Schristos srcSizes, 839*3117ece4Schristos cPtrs, 840*3117ece4Schristos cCapacities, 841*3117ece4Schristos cSizes, 842*3117ece4Schristos resPtrs, 843*3117ece4Schristos resSizes, 844*3117ece4Schristos &resultBuffer, 845*3117ece4Schristos compressedBuffer, 846*3117ece4Schristos maxCompressedSize, 847*3117ece4Schristos timeStateCompress, 848*3117ece4Schristos timeStateDecompress, 849*3117ece4Schristos srcBuffer, 850*3117ece4Schristos srcSize, 851*3117ece4Schristos fileSizes, 852*3117ece4Schristos nbFiles, 853*3117ece4Schristos cLevel, 854*3117ece4Schristos comprParams, 855*3117ece4Schristos dictBuffer, 856*3117ece4Schristos dictBufferSize, 857*3117ece4Schristos cctx, 858*3117ece4Schristos dctx, 859*3117ece4Schristos displayLevel, 860*3117ece4Schristos displayName, 861*3117ece4Schristos adv); 862*3117ece4Schristos } 863*3117ece4Schristos 864*3117ece4Schristos /* clean up */ 865*3117ece4Schristos BMK_freeTimedFnState(timeStateCompress); 866*3117ece4Schristos BMK_freeTimedFnState(timeStateDecompress); 867*3117ece4Schristos 868*3117ece4Schristos ZSTD_freeCCtx(cctx); 869*3117ece4Schristos ZSTD_freeDCtx(dctx); 870*3117ece4Schristos 871*3117ece4Schristos free(internalDstBuffer); 872*3117ece4Schristos free(resultBuffer); 873*3117ece4Schristos 874*3117ece4Schristos free((void*)srcPtrs); 875*3117ece4Schristos free(srcSizes); 876*3117ece4Schristos free(cPtrs); 877*3117ece4Schristos free(cSizes); 878*3117ece4Schristos free(cCapacities); 879*3117ece4Schristos free(resPtrs); 880*3117ece4Schristos free(resSizes); 881*3117ece4Schristos 882*3117ece4Schristos if (allocationincomplete) { 883*3117ece4Schristos RETURN_ERROR( 884*3117ece4Schristos 31, BMK_benchOutcome_t, "allocation error : not enough memory"); 885*3117ece4Schristos } 886*3117ece4Schristos 887*3117ece4Schristos if (dstParamsError) { 888*3117ece4Schristos RETURN_ERROR(32, BMK_benchOutcome_t, "Dst parameters not coherent"); 889*3117ece4Schristos } 890*3117ece4Schristos return outcome; 891*3117ece4Schristos } 892*3117ece4Schristos 893*3117ece4Schristos BMK_benchOutcome_t BMK_benchMem( 894*3117ece4Schristos const void* srcBuffer, 895*3117ece4Schristos size_t srcSize, 896*3117ece4Schristos const size_t* fileSizes, 897*3117ece4Schristos unsigned nbFiles, 898*3117ece4Schristos int cLevel, 899*3117ece4Schristos const ZSTD_compressionParameters* comprParams, 900*3117ece4Schristos const void* dictBuffer, 901*3117ece4Schristos size_t dictBufferSize, 902*3117ece4Schristos int displayLevel, 903*3117ece4Schristos const char* displayName) 904*3117ece4Schristos { 905*3117ece4Schristos BMK_advancedParams_t const adv = BMK_initAdvancedParams(); 906*3117ece4Schristos return BMK_benchMemAdvanced( 907*3117ece4Schristos srcBuffer, 908*3117ece4Schristos srcSize, 909*3117ece4Schristos NULL, 910*3117ece4Schristos 0, 911*3117ece4Schristos fileSizes, 912*3117ece4Schristos nbFiles, 913*3117ece4Schristos cLevel, 914*3117ece4Schristos comprParams, 915*3117ece4Schristos dictBuffer, 916*3117ece4Schristos dictBufferSize, 917*3117ece4Schristos displayLevel, 918*3117ece4Schristos displayName, 919*3117ece4Schristos &adv); 920*3117ece4Schristos } 921*3117ece4Schristos 922*3117ece4Schristos static BMK_benchOutcome_t BMK_benchCLevel( 923*3117ece4Schristos const void* srcBuffer, 924*3117ece4Schristos size_t benchedSize, 925*3117ece4Schristos const size_t* fileSizes, 926*3117ece4Schristos unsigned nbFiles, 927*3117ece4Schristos int cLevel, 928*3117ece4Schristos const ZSTD_compressionParameters* comprParams, 929*3117ece4Schristos const void* dictBuffer, 930*3117ece4Schristos size_t dictBufferSize, 931*3117ece4Schristos int displayLevel, 932*3117ece4Schristos const char* displayName, 933*3117ece4Schristos BMK_advancedParams_t const* const adv) 934*3117ece4Schristos { 935*3117ece4Schristos const char* pch = strrchr(displayName, '\\'); /* Windows */ 936*3117ece4Schristos if (!pch) 937*3117ece4Schristos pch = strrchr(displayName, '/'); /* Linux */ 938*3117ece4Schristos if (pch) 939*3117ece4Schristos displayName = pch + 1; 940*3117ece4Schristos 941*3117ece4Schristos if (adv->realTime) { 942*3117ece4Schristos DISPLAYLEVEL(2, "Note : switching to real-time priority \n"); 943*3117ece4Schristos SET_REALTIME_PRIORITY; 944*3117ece4Schristos } 945*3117ece4Schristos 946*3117ece4Schristos if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */ 947*3117ece4Schristos OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n", 948*3117ece4Schristos ZSTD_VERSION_STRING, 949*3117ece4Schristos ZSTD_GIT_COMMIT_STRING, 950*3117ece4Schristos (unsigned)benchedSize, 951*3117ece4Schristos adv->nbSeconds, 952*3117ece4Schristos (unsigned)(adv->blockSize >> 10)); 953*3117ece4Schristos 954*3117ece4Schristos return BMK_benchMemAdvanced( 955*3117ece4Schristos srcBuffer, 956*3117ece4Schristos benchedSize, 957*3117ece4Schristos NULL, 958*3117ece4Schristos 0, 959*3117ece4Schristos fileSizes, 960*3117ece4Schristos nbFiles, 961*3117ece4Schristos cLevel, 962*3117ece4Schristos comprParams, 963*3117ece4Schristos dictBuffer, 964*3117ece4Schristos dictBufferSize, 965*3117ece4Schristos displayLevel, 966*3117ece4Schristos displayName, 967*3117ece4Schristos adv); 968*3117ece4Schristos } 969*3117ece4Schristos 970*3117ece4Schristos int BMK_syntheticTest( 971*3117ece4Schristos int cLevel, 972*3117ece4Schristos double compressibility, 973*3117ece4Schristos const ZSTD_compressionParameters* compressionParams, 974*3117ece4Schristos int displayLevel, 975*3117ece4Schristos const BMK_advancedParams_t* adv) 976*3117ece4Schristos { 977*3117ece4Schristos char nameBuff[20] = { 0 }; 978*3117ece4Schristos const char* name = nameBuff; 979*3117ece4Schristos size_t const benchedSize = adv->blockSize ? adv->blockSize : 10000000; 980*3117ece4Schristos void* srcBuffer; 981*3117ece4Schristos BMK_benchOutcome_t res; 982*3117ece4Schristos 983*3117ece4Schristos if (cLevel > ZSTD_maxCLevel()) { 984*3117ece4Schristos DISPLAYLEVEL(1, "Invalid Compression Level"); 985*3117ece4Schristos return 15; 986*3117ece4Schristos } 987*3117ece4Schristos 988*3117ece4Schristos /* Memory allocation */ 989*3117ece4Schristos srcBuffer = malloc(benchedSize); 990*3117ece4Schristos if (!srcBuffer) { 991*3117ece4Schristos DISPLAYLEVEL(1, "allocation error : not enough memory"); 992*3117ece4Schristos return 16; 993*3117ece4Schristos } 994*3117ece4Schristos 995*3117ece4Schristos /* Fill input buffer */ 996*3117ece4Schristos if (compressibility < 0.0) { 997*3117ece4Schristos LOREM_genBuffer(srcBuffer, benchedSize, 0); 998*3117ece4Schristos name = "Lorem ipsum"; 999*3117ece4Schristos } else { 1000*3117ece4Schristos RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0); 1001*3117ece4Schristos formatString_u( 1002*3117ece4Schristos nameBuff, 1003*3117ece4Schristos sizeof(nameBuff), 1004*3117ece4Schristos "Synthetic %u%%", 1005*3117ece4Schristos (unsigned)(compressibility * 100)); 1006*3117ece4Schristos } 1007*3117ece4Schristos 1008*3117ece4Schristos /* Bench */ 1009*3117ece4Schristos res = BMK_benchCLevel( 1010*3117ece4Schristos srcBuffer, 1011*3117ece4Schristos benchedSize, 1012*3117ece4Schristos &benchedSize /* ? */, 1013*3117ece4Schristos 1 /* ? */, 1014*3117ece4Schristos cLevel, 1015*3117ece4Schristos compressionParams, 1016*3117ece4Schristos NULL, 1017*3117ece4Schristos 0, /* dictionary */ 1018*3117ece4Schristos displayLevel, 1019*3117ece4Schristos name, 1020*3117ece4Schristos adv); 1021*3117ece4Schristos 1022*3117ece4Schristos /* clean up */ 1023*3117ece4Schristos free(srcBuffer); 1024*3117ece4Schristos 1025*3117ece4Schristos return !BMK_isSuccessful_benchOutcome(res); 1026*3117ece4Schristos } 1027*3117ece4Schristos 1028*3117ece4Schristos static size_t BMK_findMaxMem(U64 requiredMem) 1029*3117ece4Schristos { 1030*3117ece4Schristos size_t const step = 64 MB; 1031*3117ece4Schristos BYTE* testmem = NULL; 1032*3117ece4Schristos 1033*3117ece4Schristos requiredMem = (((requiredMem >> 26) + 1) << 26); 1034*3117ece4Schristos requiredMem += step; 1035*3117ece4Schristos if (requiredMem > maxMemory) 1036*3117ece4Schristos requiredMem = maxMemory; 1037*3117ece4Schristos 1038*3117ece4Schristos do { 1039*3117ece4Schristos testmem = (BYTE*)malloc((size_t)requiredMem); 1040*3117ece4Schristos requiredMem -= step; 1041*3117ece4Schristos } while (!testmem && requiredMem > 0); 1042*3117ece4Schristos 1043*3117ece4Schristos free(testmem); 1044*3117ece4Schristos return (size_t)(requiredMem); 1045*3117ece4Schristos } 1046*3117ece4Schristos 1047*3117ece4Schristos /*! BMK_loadFiles() : 1048*3117ece4Schristos * Loads `buffer` with content of files listed within `fileNamesTable`. 1049*3117ece4Schristos * At most, fills `buffer` entirely. */ 1050*3117ece4Schristos static int BMK_loadFiles( 1051*3117ece4Schristos void* buffer, 1052*3117ece4Schristos size_t bufferSize, 1053*3117ece4Schristos size_t* fileSizes, 1054*3117ece4Schristos const char* const* fileNamesTable, 1055*3117ece4Schristos unsigned nbFiles, 1056*3117ece4Schristos int displayLevel) 1057*3117ece4Schristos { 1058*3117ece4Schristos size_t pos = 0, totalSize = 0; 1059*3117ece4Schristos unsigned n; 1060*3117ece4Schristos for (n = 0; n < nbFiles; n++) { 1061*3117ece4Schristos U64 fileSize = UTIL_getFileSize( 1062*3117ece4Schristos fileNamesTable[n]); /* last file may be shortened */ 1063*3117ece4Schristos if (UTIL_isDirectory(fileNamesTable[n])) { 1064*3117ece4Schristos DISPLAYLEVEL( 1065*3117ece4Schristos 2, "Ignoring %s directory... \n", fileNamesTable[n]); 1066*3117ece4Schristos fileSizes[n] = 0; 1067*3117ece4Schristos continue; 1068*3117ece4Schristos } 1069*3117ece4Schristos if (fileSize == UTIL_FILESIZE_UNKNOWN) { 1070*3117ece4Schristos DISPLAYLEVEL( 1071*3117ece4Schristos 2, 1072*3117ece4Schristos "Cannot evaluate size of %s, ignoring ... \n", 1073*3117ece4Schristos fileNamesTable[n]); 1074*3117ece4Schristos fileSizes[n] = 0; 1075*3117ece4Schristos continue; 1076*3117ece4Schristos } 1077*3117ece4Schristos { 1078*3117ece4Schristos FILE* const f = fopen(fileNamesTable[n], "rb"); 1079*3117ece4Schristos if (f == NULL) 1080*3117ece4Schristos RETURN_ERROR_INT( 1081*3117ece4Schristos 10, "impossible to open file %s", fileNamesTable[n]); 1082*3117ece4Schristos OUTPUTLEVEL(2, "Loading %s... \r", fileNamesTable[n]); 1083*3117ece4Schristos if (fileSize > bufferSize - pos) 1084*3117ece4Schristos fileSize = bufferSize - pos, 1085*3117ece4Schristos nbFiles = n; /* buffer too small - stop after this file */ 1086*3117ece4Schristos { 1087*3117ece4Schristos size_t const readSize = 1088*3117ece4Schristos fread(((char*)buffer) + pos, 1, (size_t)fileSize, f); 1089*3117ece4Schristos if (readSize != (size_t)fileSize) 1090*3117ece4Schristos RETURN_ERROR_INT( 1091*3117ece4Schristos 11, "could not read %s", fileNamesTable[n]); 1092*3117ece4Schristos pos += readSize; 1093*3117ece4Schristos } 1094*3117ece4Schristos fileSizes[n] = (size_t)fileSize; 1095*3117ece4Schristos totalSize += (size_t)fileSize; 1096*3117ece4Schristos fclose(f); 1097*3117ece4Schristos } 1098*3117ece4Schristos } 1099*3117ece4Schristos 1100*3117ece4Schristos if (totalSize == 0) 1101*3117ece4Schristos RETURN_ERROR_INT(12, "no data to bench"); 1102*3117ece4Schristos return 0; 1103*3117ece4Schristos } 1104*3117ece4Schristos 1105*3117ece4Schristos int BMK_benchFilesAdvanced( 1106*3117ece4Schristos const char* const* fileNamesTable, 1107*3117ece4Schristos unsigned nbFiles, 1108*3117ece4Schristos const char* dictFileName, 1109*3117ece4Schristos int cLevel, 1110*3117ece4Schristos const ZSTD_compressionParameters* compressionParams, 1111*3117ece4Schristos int displayLevel, 1112*3117ece4Schristos const BMK_advancedParams_t* adv) 1113*3117ece4Schristos { 1114*3117ece4Schristos void* srcBuffer = NULL; 1115*3117ece4Schristos size_t benchedSize; 1116*3117ece4Schristos void* dictBuffer = NULL; 1117*3117ece4Schristos size_t dictBufferSize = 0; 1118*3117ece4Schristos size_t* fileSizes = NULL; 1119*3117ece4Schristos BMK_benchOutcome_t res; 1120*3117ece4Schristos U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles); 1121*3117ece4Schristos 1122*3117ece4Schristos if (!nbFiles) { 1123*3117ece4Schristos DISPLAYLEVEL(1, "No Files to Benchmark"); 1124*3117ece4Schristos return 13; 1125*3117ece4Schristos } 1126*3117ece4Schristos 1127*3117ece4Schristos if (cLevel > ZSTD_maxCLevel()) { 1128*3117ece4Schristos DISPLAYLEVEL(1, "Invalid Compression Level"); 1129*3117ece4Schristos return 14; 1130*3117ece4Schristos } 1131*3117ece4Schristos 1132*3117ece4Schristos if (totalSizeToLoad == UTIL_FILESIZE_UNKNOWN) { 1133*3117ece4Schristos DISPLAYLEVEL(1, "Error loading files"); 1134*3117ece4Schristos return 15; 1135*3117ece4Schristos } 1136*3117ece4Schristos 1137*3117ece4Schristos fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t)); 1138*3117ece4Schristos if (!fileSizes) { 1139*3117ece4Schristos DISPLAYLEVEL(1, "not enough memory for fileSizes"); 1140*3117ece4Schristos return 16; 1141*3117ece4Schristos } 1142*3117ece4Schristos 1143*3117ece4Schristos /* Load dictionary */ 1144*3117ece4Schristos if (dictFileName != NULL) { 1145*3117ece4Schristos U64 const dictFileSize = UTIL_getFileSize(dictFileName); 1146*3117ece4Schristos if (dictFileSize == UTIL_FILESIZE_UNKNOWN) { 1147*3117ece4Schristos DISPLAYLEVEL( 1148*3117ece4Schristos 1, 1149*3117ece4Schristos "error loading %s : %s \n", 1150*3117ece4Schristos dictFileName, 1151*3117ece4Schristos strerror(errno)); 1152*3117ece4Schristos free(fileSizes); 1153*3117ece4Schristos DISPLAYLEVEL(1, "benchmark aborted"); 1154*3117ece4Schristos return 17; 1155*3117ece4Schristos } 1156*3117ece4Schristos if (dictFileSize > 64 MB) { 1157*3117ece4Schristos free(fileSizes); 1158*3117ece4Schristos DISPLAYLEVEL(1, "dictionary file %s too large", dictFileName); 1159*3117ece4Schristos return 18; 1160*3117ece4Schristos } 1161*3117ece4Schristos dictBufferSize = (size_t)dictFileSize; 1162*3117ece4Schristos dictBuffer = malloc(dictBufferSize); 1163*3117ece4Schristos if (dictBuffer == NULL) { 1164*3117ece4Schristos free(fileSizes); 1165*3117ece4Schristos DISPLAYLEVEL( 1166*3117ece4Schristos 1, 1167*3117ece4Schristos "not enough memory for dictionary (%u bytes)", 1168*3117ece4Schristos (unsigned)dictBufferSize); 1169*3117ece4Schristos return 19; 1170*3117ece4Schristos } 1171*3117ece4Schristos 1172*3117ece4Schristos { 1173*3117ece4Schristos int const errorCode = BMK_loadFiles( 1174*3117ece4Schristos dictBuffer, 1175*3117ece4Schristos dictBufferSize, 1176*3117ece4Schristos fileSizes, 1177*3117ece4Schristos &dictFileName /*?*/, 1178*3117ece4Schristos 1 /*?*/, 1179*3117ece4Schristos displayLevel); 1180*3117ece4Schristos if (errorCode) { 1181*3117ece4Schristos res = BMK_benchOutcome_error(); 1182*3117ece4Schristos goto _cleanUp; 1183*3117ece4Schristos } 1184*3117ece4Schristos } 1185*3117ece4Schristos } 1186*3117ece4Schristos 1187*3117ece4Schristos /* Memory allocation & restrictions */ 1188*3117ece4Schristos benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3; 1189*3117ece4Schristos if ((U64)benchedSize > totalSizeToLoad) 1190*3117ece4Schristos benchedSize = (size_t)totalSizeToLoad; 1191*3117ece4Schristos if (benchedSize < totalSizeToLoad) 1192*3117ece4Schristos DISPLAY("Not enough memory; testing %u MB only...\n", 1193*3117ece4Schristos (unsigned)(benchedSize >> 20)); 1194*3117ece4Schristos 1195*3117ece4Schristos srcBuffer = benchedSize ? malloc(benchedSize) : NULL; 1196*3117ece4Schristos if (!srcBuffer) { 1197*3117ece4Schristos free(dictBuffer); 1198*3117ece4Schristos free(fileSizes); 1199*3117ece4Schristos DISPLAYLEVEL(1, "not enough memory for srcBuffer"); 1200*3117ece4Schristos return 20; 1201*3117ece4Schristos } 1202*3117ece4Schristos 1203*3117ece4Schristos /* Load input buffer */ 1204*3117ece4Schristos { 1205*3117ece4Schristos int const errorCode = BMK_loadFiles( 1206*3117ece4Schristos srcBuffer, 1207*3117ece4Schristos benchedSize, 1208*3117ece4Schristos fileSizes, 1209*3117ece4Schristos fileNamesTable, 1210*3117ece4Schristos nbFiles, 1211*3117ece4Schristos displayLevel); 1212*3117ece4Schristos if (errorCode) { 1213*3117ece4Schristos res = BMK_benchOutcome_error(); 1214*3117ece4Schristos goto _cleanUp; 1215*3117ece4Schristos } 1216*3117ece4Schristos } 1217*3117ece4Schristos 1218*3117ece4Schristos /* Bench */ 1219*3117ece4Schristos { 1220*3117ece4Schristos char mfName[20] = { 0 }; 1221*3117ece4Schristos formatString_u(mfName, sizeof(mfName), " %u files", nbFiles); 1222*3117ece4Schristos { 1223*3117ece4Schristos const char* const displayName = 1224*3117ece4Schristos (nbFiles > 1) ? mfName : fileNamesTable[0]; 1225*3117ece4Schristos res = BMK_benchCLevel( 1226*3117ece4Schristos srcBuffer, 1227*3117ece4Schristos benchedSize, 1228*3117ece4Schristos fileSizes, 1229*3117ece4Schristos nbFiles, 1230*3117ece4Schristos cLevel, 1231*3117ece4Schristos compressionParams, 1232*3117ece4Schristos dictBuffer, 1233*3117ece4Schristos dictBufferSize, 1234*3117ece4Schristos displayLevel, 1235*3117ece4Schristos displayName, 1236*3117ece4Schristos adv); 1237*3117ece4Schristos } 1238*3117ece4Schristos } 1239*3117ece4Schristos 1240*3117ece4Schristos _cleanUp: 1241*3117ece4Schristos free(srcBuffer); 1242*3117ece4Schristos free(dictBuffer); 1243*3117ece4Schristos free(fileSizes); 1244*3117ece4Schristos return !BMK_isSuccessful_benchOutcome(res); 1245*3117ece4Schristos } 1246*3117ece4Schristos 1247*3117ece4Schristos int BMK_benchFiles( 1248*3117ece4Schristos const char* const* fileNamesTable, 1249*3117ece4Schristos unsigned nbFiles, 1250*3117ece4Schristos const char* dictFileName, 1251*3117ece4Schristos int cLevel, 1252*3117ece4Schristos const ZSTD_compressionParameters* compressionParams, 1253*3117ece4Schristos int displayLevel) 1254*3117ece4Schristos { 1255*3117ece4Schristos BMK_advancedParams_t const adv = BMK_initAdvancedParams(); 1256*3117ece4Schristos return BMK_benchFilesAdvanced( 1257*3117ece4Schristos fileNamesTable, 1258*3117ece4Schristos nbFiles, 1259*3117ece4Schristos dictFileName, 1260*3117ece4Schristos cLevel, 1261*3117ece4Schristos compressionParams, 1262*3117ece4Schristos displayLevel, 1263*3117ece4Schristos &adv); 1264*3117ece4Schristos } 1265