1*a0483764SConrad Meyer /* 2*a0483764SConrad Meyer * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3*a0483764SConrad Meyer * All rights reserved. 4*a0483764SConrad Meyer * 5*a0483764SConrad Meyer * This source code is licensed under both the BSD-style license (found in the 6*a0483764SConrad Meyer * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*a0483764SConrad Meyer * in the COPYING file in the root directory of this source tree). 8*a0483764SConrad Meyer * You may select, at your option, one of the above-listed licenses. 9*a0483764SConrad Meyer */ 10*a0483764SConrad Meyer 11*a0483764SConrad Meyer 12*a0483764SConrad Meyer /* ************************************** 13*a0483764SConrad Meyer * Tuning parameters 14*a0483764SConrad Meyer ****************************************/ 15*a0483764SConrad Meyer #ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */ 16*a0483764SConrad Meyer #define BMK_TIMETEST_DEFAULT_S 3 17*a0483764SConrad Meyer #endif 18*a0483764SConrad Meyer 19*a0483764SConrad Meyer 20*a0483764SConrad Meyer /* ************************************* 21*a0483764SConrad Meyer * Includes 22*a0483764SConrad Meyer ***************************************/ 23*a0483764SConrad Meyer #include "platform.h" /* Large Files support */ 24*a0483764SConrad Meyer #include "util.h" /* UTIL_getFileSize, UTIL_sleep */ 25*a0483764SConrad Meyer #include <stdlib.h> /* malloc, free */ 26*a0483764SConrad Meyer #include <string.h> /* memset, strerror */ 27*a0483764SConrad Meyer #include <stdio.h> /* fprintf, fopen */ 28*a0483764SConrad Meyer #include <errno.h> 29*a0483764SConrad Meyer #include <assert.h> /* assert */ 30*a0483764SConrad Meyer 31*a0483764SConrad Meyer #include "benchfn.h" 32*a0483764SConrad Meyer #include "mem.h" 33*a0483764SConrad Meyer #define ZSTD_STATIC_LINKING_ONLY 34*a0483764SConrad Meyer #include "zstd.h" 35*a0483764SConrad Meyer #include "datagen.h" /* RDG_genBuffer */ 36*a0483764SConrad Meyer #include "xxhash.h" 37*a0483764SConrad Meyer #include "benchzstd.h" 38*a0483764SConrad Meyer #include "zstd_errors.h" 39*a0483764SConrad Meyer 40*a0483764SConrad Meyer 41*a0483764SConrad Meyer /* ************************************* 42*a0483764SConrad Meyer * Constants 43*a0483764SConrad Meyer ***************************************/ 44*a0483764SConrad Meyer #ifndef ZSTD_GIT_COMMIT 45*a0483764SConrad Meyer # define ZSTD_GIT_COMMIT_STRING "" 46*a0483764SConrad Meyer #else 47*a0483764SConrad Meyer # define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT) 48*a0483764SConrad Meyer #endif 49*a0483764SConrad Meyer 50*a0483764SConrad Meyer #define TIMELOOP_MICROSEC (1*1000000ULL) /* 1 second */ 51*a0483764SConrad Meyer #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ 52*a0483764SConrad Meyer #define ACTIVEPERIOD_MICROSEC (70*TIMELOOP_MICROSEC) /* 70 seconds */ 53*a0483764SConrad Meyer #define COOLPERIOD_SEC 10 54*a0483764SConrad Meyer 55*a0483764SConrad Meyer #define KB *(1 <<10) 56*a0483764SConrad Meyer #define MB *(1 <<20) 57*a0483764SConrad Meyer #define GB *(1U<<30) 58*a0483764SConrad Meyer 59*a0483764SConrad Meyer #define BMK_RUNTEST_DEFAULT_MS 1000 60*a0483764SConrad Meyer 61*a0483764SConrad Meyer static const size_t maxMemory = (sizeof(size_t)==4) ? 62*a0483764SConrad Meyer /* 32-bit */ (2 GB - 64 MB) : 63*a0483764SConrad Meyer /* 64-bit */ (size_t)(1ULL << ((sizeof(size_t)*8)-31)); 64*a0483764SConrad Meyer 65*a0483764SConrad Meyer 66*a0483764SConrad Meyer /* ************************************* 67*a0483764SConrad Meyer * console display 68*a0483764SConrad Meyer ***************************************/ 69*a0483764SConrad Meyer #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) 70*a0483764SConrad Meyer #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } 71*a0483764SConrad Meyer /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */ 72*a0483764SConrad Meyer 73*a0483764SConrad Meyer static const U64 g_refreshRate = SEC_TO_MICRO / 6; 74*a0483764SConrad Meyer static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; 75*a0483764SConrad Meyer 76*a0483764SConrad Meyer #define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \ 77*a0483764SConrad Meyer if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \ 78*a0483764SConrad Meyer { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ 79*a0483764SConrad Meyer if (displayLevel>=4) fflush(stderr); } } } 80*a0483764SConrad Meyer 81*a0483764SConrad Meyer 82*a0483764SConrad Meyer /* ************************************* 83*a0483764SConrad Meyer * Exceptions 84*a0483764SConrad Meyer ***************************************/ 85*a0483764SConrad Meyer #ifndef DEBUG 86*a0483764SConrad Meyer # define DEBUG 0 87*a0483764SConrad Meyer #endif 88*a0483764SConrad Meyer #define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); } 89*a0483764SConrad Meyer 90*a0483764SConrad Meyer #define EXM_THROW_INT(errorNum, ...) { \ 91*a0483764SConrad Meyer DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 92*a0483764SConrad Meyer DISPLAYLEVEL(1, "Error %i : ", errorNum); \ 93*a0483764SConrad Meyer DISPLAYLEVEL(1, __VA_ARGS__); \ 94*a0483764SConrad Meyer DISPLAYLEVEL(1, " \n"); \ 95*a0483764SConrad Meyer return errorNum; \ 96*a0483764SConrad Meyer } 97*a0483764SConrad Meyer 98*a0483764SConrad Meyer #define CHECK_Z(zf) { \ 99*a0483764SConrad Meyer size_t const zerr = zf; \ 100*a0483764SConrad Meyer if (ZSTD_isError(zerr)) { \ 101*a0483764SConrad Meyer DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 102*a0483764SConrad Meyer DISPLAY("Error : "); \ 103*a0483764SConrad Meyer DISPLAY("%s failed : %s", \ 104*a0483764SConrad Meyer #zf, ZSTD_getErrorName(zerr)); \ 105*a0483764SConrad Meyer DISPLAY(" \n"); \ 106*a0483764SConrad Meyer exit(1); \ 107*a0483764SConrad Meyer } \ 108*a0483764SConrad Meyer } 109*a0483764SConrad Meyer 110*a0483764SConrad Meyer #define RETURN_ERROR(errorNum, retType, ...) { \ 111*a0483764SConrad Meyer retType r; \ 112*a0483764SConrad Meyer memset(&r, 0, sizeof(retType)); \ 113*a0483764SConrad Meyer DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ 114*a0483764SConrad Meyer DISPLAYLEVEL(1, "Error %i : ", errorNum); \ 115*a0483764SConrad Meyer DISPLAYLEVEL(1, __VA_ARGS__); \ 116*a0483764SConrad Meyer DISPLAYLEVEL(1, " \n"); \ 117*a0483764SConrad Meyer r.tag = errorNum; \ 118*a0483764SConrad Meyer return r; \ 119*a0483764SConrad Meyer } 120*a0483764SConrad Meyer 121*a0483764SConrad Meyer 122*a0483764SConrad Meyer /* ************************************* 123*a0483764SConrad Meyer * Benchmark Parameters 124*a0483764SConrad Meyer ***************************************/ 125*a0483764SConrad Meyer 126*a0483764SConrad Meyer BMK_advancedParams_t BMK_initAdvancedParams(void) { 127*a0483764SConrad Meyer BMK_advancedParams_t const res = { 128*a0483764SConrad Meyer BMK_both, /* mode */ 129*a0483764SConrad Meyer BMK_TIMETEST_DEFAULT_S, /* nbSeconds */ 130*a0483764SConrad Meyer 0, /* blockSize */ 131*a0483764SConrad Meyer 0, /* nbWorkers */ 132*a0483764SConrad Meyer 0, /* realTime */ 133*a0483764SConrad Meyer 0, /* additionalParam */ 134*a0483764SConrad Meyer 0, /* ldmFlag */ 135*a0483764SConrad Meyer 0, /* ldmMinMatch */ 136*a0483764SConrad Meyer 0, /* ldmHashLog */ 137*a0483764SConrad Meyer 0, /* ldmBuckSizeLog */ 138*a0483764SConrad Meyer 0 /* ldmHashRateLog */ 139*a0483764SConrad Meyer }; 140*a0483764SConrad Meyer return res; 141*a0483764SConrad Meyer } 142*a0483764SConrad Meyer 143*a0483764SConrad Meyer 144*a0483764SConrad Meyer /* ******************************************************** 145*a0483764SConrad Meyer * Bench functions 146*a0483764SConrad Meyer **********************************************************/ 147*a0483764SConrad Meyer typedef struct { 148*a0483764SConrad Meyer const void* srcPtr; 149*a0483764SConrad Meyer size_t srcSize; 150*a0483764SConrad Meyer void* cPtr; 151*a0483764SConrad Meyer size_t cRoom; 152*a0483764SConrad Meyer size_t cSize; 153*a0483764SConrad Meyer void* resPtr; 154*a0483764SConrad Meyer size_t resSize; 155*a0483764SConrad Meyer } blockParam_t; 156*a0483764SConrad Meyer 157*a0483764SConrad Meyer #undef MIN 158*a0483764SConrad Meyer #undef MAX 159*a0483764SConrad Meyer #define MIN(a,b) ((a) < (b) ? (a) : (b)) 160*a0483764SConrad Meyer #define MAX(a,b) ((a) > (b) ? (a) : (b)) 161*a0483764SConrad Meyer 162*a0483764SConrad Meyer static void BMK_initCCtx(ZSTD_CCtx* ctx, 163*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize, int cLevel, 164*a0483764SConrad Meyer const ZSTD_compressionParameters* comprParams, const BMK_advancedParams_t* adv) { 165*a0483764SConrad Meyer ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters); 166*a0483764SConrad Meyer if (adv->nbWorkers==1) { 167*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0)); 168*a0483764SConrad Meyer } else { 169*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers)); 170*a0483764SConrad Meyer } 171*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel)); 172*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag)); 173*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch)); 174*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog)); 175*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog)); 176*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog)); 177*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, comprParams->windowLog)); 178*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, comprParams->hashLog)); 179*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, comprParams->chainLog)); 180*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, comprParams->searchLog)); 181*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, comprParams->minMatch)); 182*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, comprParams->targetLength)); 183*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, comprParams->strategy)); 184*a0483764SConrad Meyer CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize)); 185*a0483764SConrad Meyer } 186*a0483764SConrad Meyer 187*a0483764SConrad Meyer static void BMK_initDCtx(ZSTD_DCtx* dctx, 188*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize) { 189*a0483764SConrad Meyer CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters)); 190*a0483764SConrad Meyer CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize)); 191*a0483764SConrad Meyer } 192*a0483764SConrad Meyer 193*a0483764SConrad Meyer 194*a0483764SConrad Meyer typedef struct { 195*a0483764SConrad Meyer ZSTD_CCtx* cctx; 196*a0483764SConrad Meyer const void* dictBuffer; 197*a0483764SConrad Meyer size_t dictBufferSize; 198*a0483764SConrad Meyer int cLevel; 199*a0483764SConrad Meyer const ZSTD_compressionParameters* comprParams; 200*a0483764SConrad Meyer const BMK_advancedParams_t* adv; 201*a0483764SConrad Meyer } BMK_initCCtxArgs; 202*a0483764SConrad Meyer 203*a0483764SConrad Meyer static size_t local_initCCtx(void* payload) { 204*a0483764SConrad Meyer BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload; 205*a0483764SConrad Meyer BMK_initCCtx(ag->cctx, ag->dictBuffer, ag->dictBufferSize, ag->cLevel, ag->comprParams, ag->adv); 206*a0483764SConrad Meyer return 0; 207*a0483764SConrad Meyer } 208*a0483764SConrad Meyer 209*a0483764SConrad Meyer typedef struct { 210*a0483764SConrad Meyer ZSTD_DCtx* dctx; 211*a0483764SConrad Meyer const void* dictBuffer; 212*a0483764SConrad Meyer size_t dictBufferSize; 213*a0483764SConrad Meyer } BMK_initDCtxArgs; 214*a0483764SConrad Meyer 215*a0483764SConrad Meyer static size_t local_initDCtx(void* payload) { 216*a0483764SConrad Meyer BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload; 217*a0483764SConrad Meyer BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize); 218*a0483764SConrad Meyer return 0; 219*a0483764SConrad Meyer } 220*a0483764SConrad Meyer 221*a0483764SConrad Meyer 222*a0483764SConrad Meyer /* `addArgs` is the context */ 223*a0483764SConrad Meyer static size_t local_defaultCompress( 224*a0483764SConrad Meyer const void* srcBuffer, size_t srcSize, 225*a0483764SConrad Meyer void* dstBuffer, size_t dstSize, 226*a0483764SConrad Meyer void* addArgs) 227*a0483764SConrad Meyer { 228*a0483764SConrad Meyer ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs; 229*a0483764SConrad Meyer return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize); 230*a0483764SConrad Meyer } 231*a0483764SConrad Meyer 232*a0483764SConrad Meyer /* `addArgs` is the context */ 233*a0483764SConrad Meyer static size_t local_defaultDecompress( 234*a0483764SConrad Meyer const void* srcBuffer, size_t srcSize, 235*a0483764SConrad Meyer void* dstBuffer, size_t dstCapacity, 236*a0483764SConrad Meyer void* addArgs) 237*a0483764SConrad Meyer { 238*a0483764SConrad Meyer size_t moreToFlush = 1; 239*a0483764SConrad Meyer ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs; 240*a0483764SConrad Meyer ZSTD_inBuffer in; 241*a0483764SConrad Meyer ZSTD_outBuffer out; 242*a0483764SConrad Meyer in.src = srcBuffer; in.size = srcSize; in.pos = 0; 243*a0483764SConrad Meyer out.dst = dstBuffer; out.size = dstCapacity; out.pos = 0; 244*a0483764SConrad Meyer while (moreToFlush) { 245*a0483764SConrad Meyer if(out.pos == out.size) { 246*a0483764SConrad Meyer return (size_t)-ZSTD_error_dstSize_tooSmall; 247*a0483764SConrad Meyer } 248*a0483764SConrad Meyer moreToFlush = ZSTD_decompressStream(dctx, &out, &in); 249*a0483764SConrad Meyer if (ZSTD_isError(moreToFlush)) { 250*a0483764SConrad Meyer return moreToFlush; 251*a0483764SConrad Meyer } 252*a0483764SConrad Meyer } 253*a0483764SConrad Meyer return out.pos; 254*a0483764SConrad Meyer 255*a0483764SConrad Meyer } 256*a0483764SConrad Meyer 257*a0483764SConrad Meyer 258*a0483764SConrad Meyer /* ================================================================= */ 259*a0483764SConrad Meyer /* Benchmark Zstandard, mem-to-mem scenarios */ 260*a0483764SConrad Meyer /* ================================================================= */ 261*a0483764SConrad Meyer 262*a0483764SConrad Meyer int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome) 263*a0483764SConrad Meyer { 264*a0483764SConrad Meyer return outcome.tag == 0; 265*a0483764SConrad Meyer } 266*a0483764SConrad Meyer 267*a0483764SConrad Meyer BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome) 268*a0483764SConrad Meyer { 269*a0483764SConrad Meyer assert(outcome.tag == 0); 270*a0483764SConrad Meyer return outcome.internal_never_use_directly; 271*a0483764SConrad Meyer } 272*a0483764SConrad Meyer 273*a0483764SConrad Meyer static BMK_benchOutcome_t BMK_benchOutcome_error(void) 274*a0483764SConrad Meyer { 275*a0483764SConrad Meyer BMK_benchOutcome_t b; 276*a0483764SConrad Meyer memset(&b, 0, sizeof(b)); 277*a0483764SConrad Meyer b.tag = 1; 278*a0483764SConrad Meyer return b; 279*a0483764SConrad Meyer } 280*a0483764SConrad Meyer 281*a0483764SConrad Meyer static BMK_benchOutcome_t BMK_benchOutcome_setValidResult(BMK_benchResult_t result) 282*a0483764SConrad Meyer { 283*a0483764SConrad Meyer BMK_benchOutcome_t b; 284*a0483764SConrad Meyer b.tag = 0; 285*a0483764SConrad Meyer b.internal_never_use_directly = result; 286*a0483764SConrad Meyer return b; 287*a0483764SConrad Meyer } 288*a0483764SConrad Meyer 289*a0483764SConrad Meyer 290*a0483764SConrad Meyer /* benchMem with no allocation */ 291*a0483764SConrad Meyer static BMK_benchOutcome_t 292*a0483764SConrad Meyer BMK_benchMemAdvancedNoAlloc( 293*a0483764SConrad Meyer const void** srcPtrs, size_t* srcSizes, 294*a0483764SConrad Meyer void** cPtrs, size_t* cCapacities, size_t* cSizes, 295*a0483764SConrad Meyer void** resPtrs, size_t* resSizes, 296*a0483764SConrad Meyer void** resultBufferPtr, void* compressedBuffer, 297*a0483764SConrad Meyer size_t maxCompressedSize, 298*a0483764SConrad Meyer BMK_timedFnState_t* timeStateCompress, 299*a0483764SConrad Meyer BMK_timedFnState_t* timeStateDecompress, 300*a0483764SConrad Meyer 301*a0483764SConrad Meyer const void* srcBuffer, size_t srcSize, 302*a0483764SConrad Meyer const size_t* fileSizes, unsigned nbFiles, 303*a0483764SConrad Meyer const int cLevel, 304*a0483764SConrad Meyer const ZSTD_compressionParameters* comprParams, 305*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize, 306*a0483764SConrad Meyer ZSTD_CCtx* cctx, ZSTD_DCtx* dctx, 307*a0483764SConrad Meyer int displayLevel, const char* displayName, 308*a0483764SConrad Meyer const BMK_advancedParams_t* adv) 309*a0483764SConrad Meyer { 310*a0483764SConrad Meyer size_t const blockSize = ((adv->blockSize>=32 && (adv->mode != BMK_decodeOnly)) ? adv->blockSize : srcSize) + (!srcSize); /* avoid div by 0 */ 311*a0483764SConrad Meyer BMK_benchResult_t benchResult; 312*a0483764SConrad Meyer size_t const loadedCompressedSize = srcSize; 313*a0483764SConrad Meyer size_t cSize = 0; 314*a0483764SConrad Meyer double ratio = 0.; 315*a0483764SConrad Meyer U32 nbBlocks; 316*a0483764SConrad Meyer 317*a0483764SConrad Meyer assert(cctx != NULL); assert(dctx != NULL); 318*a0483764SConrad Meyer 319*a0483764SConrad Meyer /* init */ 320*a0483764SConrad Meyer memset(&benchResult, 0, sizeof(benchResult)); 321*a0483764SConrad Meyer if (strlen(displayName)>17) displayName += strlen(displayName) - 17; /* display last 17 characters */ 322*a0483764SConrad Meyer if (adv->mode == BMK_decodeOnly) { /* benchmark only decompression : source must be already compressed */ 323*a0483764SConrad Meyer const char* srcPtr = (const char*)srcBuffer; 324*a0483764SConrad Meyer U64 totalDSize64 = 0; 325*a0483764SConrad Meyer U32 fileNb; 326*a0483764SConrad Meyer for (fileNb=0; fileNb<nbFiles; fileNb++) { 327*a0483764SConrad Meyer U64 const fSize64 = ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]); 328*a0483764SConrad Meyer if (fSize64==0) RETURN_ERROR(32, BMK_benchOutcome_t, "Impossible to determine original size "); 329*a0483764SConrad Meyer totalDSize64 += fSize64; 330*a0483764SConrad Meyer srcPtr += fileSizes[fileNb]; 331*a0483764SConrad Meyer } 332*a0483764SConrad Meyer { size_t const decodedSize = (size_t)totalDSize64; 333*a0483764SConrad Meyer assert((U64)decodedSize == totalDSize64); /* check overflow */ 334*a0483764SConrad Meyer free(*resultBufferPtr); 335*a0483764SConrad Meyer *resultBufferPtr = malloc(decodedSize); 336*a0483764SConrad Meyer if (!(*resultBufferPtr)) { 337*a0483764SConrad Meyer RETURN_ERROR(33, BMK_benchOutcome_t, "not enough memory"); 338*a0483764SConrad Meyer } 339*a0483764SConrad Meyer if (totalDSize64 > decodedSize) { /* size_t overflow */ 340*a0483764SConrad Meyer free(*resultBufferPtr); 341*a0483764SConrad Meyer RETURN_ERROR(32, BMK_benchOutcome_t, "original size is too large"); 342*a0483764SConrad Meyer } 343*a0483764SConrad Meyer cSize = srcSize; 344*a0483764SConrad Meyer srcSize = decodedSize; 345*a0483764SConrad Meyer ratio = (double)srcSize / (double)cSize; 346*a0483764SConrad Meyer } 347*a0483764SConrad Meyer } 348*a0483764SConrad Meyer 349*a0483764SConrad Meyer /* Init data blocks */ 350*a0483764SConrad Meyer { const char* srcPtr = (const char*)srcBuffer; 351*a0483764SConrad Meyer char* cPtr = (char*)compressedBuffer; 352*a0483764SConrad Meyer char* resPtr = (char*)(*resultBufferPtr); 353*a0483764SConrad Meyer U32 fileNb; 354*a0483764SConrad Meyer for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) { 355*a0483764SConrad Meyer size_t remaining = fileSizes[fileNb]; 356*a0483764SConrad Meyer U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly) ? 1 : (U32)((remaining + (blockSize-1)) / blockSize); 357*a0483764SConrad Meyer U32 const blockEnd = nbBlocks + nbBlocksforThisFile; 358*a0483764SConrad Meyer for ( ; nbBlocks<blockEnd; nbBlocks++) { 359*a0483764SConrad Meyer size_t const thisBlockSize = MIN(remaining, blockSize); 360*a0483764SConrad Meyer srcPtrs[nbBlocks] = srcPtr; 361*a0483764SConrad Meyer srcSizes[nbBlocks] = thisBlockSize; 362*a0483764SConrad Meyer cPtrs[nbBlocks] = cPtr; 363*a0483764SConrad Meyer cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly) ? thisBlockSize : ZSTD_compressBound(thisBlockSize); 364*a0483764SConrad Meyer resPtrs[nbBlocks] = resPtr; 365*a0483764SConrad Meyer resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly) ? (size_t) ZSTD_findDecompressedSize(srcPtr, thisBlockSize) : thisBlockSize; 366*a0483764SConrad Meyer srcPtr += thisBlockSize; 367*a0483764SConrad Meyer cPtr += cCapacities[nbBlocks]; 368*a0483764SConrad Meyer resPtr += thisBlockSize; 369*a0483764SConrad Meyer remaining -= thisBlockSize; 370*a0483764SConrad Meyer if (adv->mode == BMK_decodeOnly) { 371*a0483764SConrad Meyer assert(nbBlocks==0); 372*a0483764SConrad Meyer cSizes[nbBlocks] = thisBlockSize; 373*a0483764SConrad Meyer benchResult.cSize = thisBlockSize; 374*a0483764SConrad Meyer } 375*a0483764SConrad Meyer } 376*a0483764SConrad Meyer } 377*a0483764SConrad Meyer } 378*a0483764SConrad Meyer 379*a0483764SConrad Meyer /* warmimg up `compressedBuffer` */ 380*a0483764SConrad Meyer if (adv->mode == BMK_decodeOnly) { 381*a0483764SConrad Meyer memcpy(compressedBuffer, srcBuffer, loadedCompressedSize); 382*a0483764SConrad Meyer } else { 383*a0483764SConrad Meyer RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1); 384*a0483764SConrad Meyer } 385*a0483764SConrad Meyer 386*a0483764SConrad Meyer /* Bench */ 387*a0483764SConrad Meyer { U64 const crcOrig = (adv->mode == BMK_decodeOnly) ? 0 : XXH64(srcBuffer, srcSize, 0); 388*a0483764SConrad Meyer # define NB_MARKS 4 389*a0483764SConrad Meyer const char* marks[NB_MARKS] = { " |", " /", " =", " \\" }; 390*a0483764SConrad Meyer U32 markNb = 0; 391*a0483764SConrad Meyer int compressionCompleted = (adv->mode == BMK_decodeOnly); 392*a0483764SConrad Meyer int decompressionCompleted = (adv->mode == BMK_compressOnly); 393*a0483764SConrad Meyer BMK_benchParams_t cbp, dbp; 394*a0483764SConrad Meyer BMK_initCCtxArgs cctxprep; 395*a0483764SConrad Meyer BMK_initDCtxArgs dctxprep; 396*a0483764SConrad Meyer 397*a0483764SConrad Meyer cbp.benchFn = local_defaultCompress; 398*a0483764SConrad Meyer cbp.benchPayload = cctx; 399*a0483764SConrad Meyer cbp.initFn = local_initCCtx; 400*a0483764SConrad Meyer cbp.initPayload = &cctxprep; 401*a0483764SConrad Meyer cbp.errorFn = ZSTD_isError; 402*a0483764SConrad Meyer cbp.blockCount = nbBlocks; 403*a0483764SConrad Meyer cbp.srcBuffers = srcPtrs; 404*a0483764SConrad Meyer cbp.srcSizes = srcSizes; 405*a0483764SConrad Meyer cbp.dstBuffers = cPtrs; 406*a0483764SConrad Meyer cbp.dstCapacities = cCapacities; 407*a0483764SConrad Meyer cbp.blockResults = cSizes; 408*a0483764SConrad Meyer 409*a0483764SConrad Meyer cctxprep.cctx = cctx; 410*a0483764SConrad Meyer cctxprep.dictBuffer = dictBuffer; 411*a0483764SConrad Meyer cctxprep.dictBufferSize = dictBufferSize; 412*a0483764SConrad Meyer cctxprep.cLevel = cLevel; 413*a0483764SConrad Meyer cctxprep.comprParams = comprParams; 414*a0483764SConrad Meyer cctxprep.adv = adv; 415*a0483764SConrad Meyer 416*a0483764SConrad Meyer dbp.benchFn = local_defaultDecompress; 417*a0483764SConrad Meyer dbp.benchPayload = dctx; 418*a0483764SConrad Meyer dbp.initFn = local_initDCtx; 419*a0483764SConrad Meyer dbp.initPayload = &dctxprep; 420*a0483764SConrad Meyer dbp.errorFn = ZSTD_isError; 421*a0483764SConrad Meyer dbp.blockCount = nbBlocks; 422*a0483764SConrad Meyer dbp.srcBuffers = (const void* const *) cPtrs; 423*a0483764SConrad Meyer dbp.srcSizes = cSizes; 424*a0483764SConrad Meyer dbp.dstBuffers = resPtrs; 425*a0483764SConrad Meyer dbp.dstCapacities = resSizes; 426*a0483764SConrad Meyer dbp.blockResults = NULL; 427*a0483764SConrad Meyer 428*a0483764SConrad Meyer dctxprep.dctx = dctx; 429*a0483764SConrad Meyer dctxprep.dictBuffer = dictBuffer; 430*a0483764SConrad Meyer dctxprep.dictBufferSize = dictBufferSize; 431*a0483764SConrad Meyer 432*a0483764SConrad Meyer DISPLAYLEVEL(2, "\r%70s\r", ""); /* blank line */ 433*a0483764SConrad Meyer DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (unsigned)srcSize); 434*a0483764SConrad Meyer 435*a0483764SConrad Meyer while (!(compressionCompleted && decompressionCompleted)) { 436*a0483764SConrad Meyer if (!compressionCompleted) { 437*a0483764SConrad Meyer BMK_runOutcome_t const cOutcome = BMK_benchTimedFn( timeStateCompress, cbp); 438*a0483764SConrad Meyer 439*a0483764SConrad Meyer if (!BMK_isSuccessful_runOutcome(cOutcome)) { 440*a0483764SConrad Meyer return BMK_benchOutcome_error(); 441*a0483764SConrad Meyer } 442*a0483764SConrad Meyer 443*a0483764SConrad Meyer { BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome); 444*a0483764SConrad Meyer cSize = cResult.sumOfReturn; 445*a0483764SConrad Meyer ratio = (double)srcSize / cSize; 446*a0483764SConrad Meyer { BMK_benchResult_t newResult; 447*a0483764SConrad Meyer newResult.cSpeed = ((U64)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun); 448*a0483764SConrad Meyer benchResult.cSize = cSize; 449*a0483764SConrad Meyer if (newResult.cSpeed > benchResult.cSpeed) 450*a0483764SConrad Meyer benchResult.cSpeed = newResult.cSpeed; 451*a0483764SConrad Meyer } } 452*a0483764SConrad Meyer 453*a0483764SConrad Meyer { int const ratioAccuracy = (ratio < 10.) ? 3 : 2; 454*a0483764SConrad Meyer DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f),%6.*f MB/s\r", 455*a0483764SConrad Meyer marks[markNb], displayName, 456*a0483764SConrad Meyer (unsigned)srcSize, (unsigned)cSize, 457*a0483764SConrad Meyer ratioAccuracy, ratio, 458*a0483764SConrad Meyer benchResult.cSpeed < (10 MB) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT); 459*a0483764SConrad Meyer } 460*a0483764SConrad Meyer compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress); 461*a0483764SConrad Meyer } 462*a0483764SConrad Meyer 463*a0483764SConrad Meyer if(!decompressionCompleted) { 464*a0483764SConrad Meyer BMK_runOutcome_t const dOutcome = BMK_benchTimedFn(timeStateDecompress, dbp); 465*a0483764SConrad Meyer 466*a0483764SConrad Meyer if(!BMK_isSuccessful_runOutcome(dOutcome)) { 467*a0483764SConrad Meyer return BMK_benchOutcome_error(); 468*a0483764SConrad Meyer } 469*a0483764SConrad Meyer 470*a0483764SConrad Meyer { BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome); 471*a0483764SConrad Meyer U64 const newDSpeed = (srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun); 472*a0483764SConrad Meyer if (newDSpeed > benchResult.dSpeed) 473*a0483764SConrad Meyer benchResult.dSpeed = newDSpeed; 474*a0483764SConrad Meyer } 475*a0483764SConrad Meyer 476*a0483764SConrad Meyer { int const ratioAccuracy = (ratio < 10.) ? 3 : 2; 477*a0483764SConrad Meyer DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f),%6.*f MB/s ,%6.1f MB/s \r", 478*a0483764SConrad Meyer marks[markNb], displayName, 479*a0483764SConrad Meyer (unsigned)srcSize, (unsigned)benchResult.cSize, 480*a0483764SConrad Meyer ratioAccuracy, ratio, 481*a0483764SConrad Meyer benchResult.cSpeed < (10 MB) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT, 482*a0483764SConrad Meyer (double)benchResult.dSpeed / MB_UNIT); 483*a0483764SConrad Meyer } 484*a0483764SConrad Meyer decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress); 485*a0483764SConrad Meyer } 486*a0483764SConrad Meyer markNb = (markNb+1) % NB_MARKS; 487*a0483764SConrad Meyer } /* while (!(compressionCompleted && decompressionCompleted)) */ 488*a0483764SConrad Meyer 489*a0483764SConrad Meyer /* CRC Checking */ 490*a0483764SConrad Meyer { const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr); 491*a0483764SConrad Meyer U64 const crcCheck = XXH64(resultBuffer, srcSize, 0); 492*a0483764SConrad Meyer if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) { 493*a0483764SConrad Meyer size_t u; 494*a0483764SConrad Meyer DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n", 495*a0483764SConrad Meyer displayName, (unsigned)crcOrig, (unsigned)crcCheck); 496*a0483764SConrad Meyer for (u=0; u<srcSize; u++) { 497*a0483764SConrad Meyer if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) { 498*a0483764SConrad Meyer unsigned segNb, bNb, pos; 499*a0483764SConrad Meyer size_t bacc = 0; 500*a0483764SConrad Meyer DISPLAY("Decoding error at pos %u ", (unsigned)u); 501*a0483764SConrad Meyer for (segNb = 0; segNb < nbBlocks; segNb++) { 502*a0483764SConrad Meyer if (bacc + srcSizes[segNb] > u) break; 503*a0483764SConrad Meyer bacc += srcSizes[segNb]; 504*a0483764SConrad Meyer } 505*a0483764SConrad Meyer pos = (U32)(u - bacc); 506*a0483764SConrad Meyer bNb = pos / (128 KB); 507*a0483764SConrad Meyer DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos); 508*a0483764SConrad Meyer if (u>5) { 509*a0483764SConrad Meyer int n; 510*a0483764SConrad Meyer DISPLAY("origin: "); 511*a0483764SConrad Meyer for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); 512*a0483764SConrad Meyer DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]); 513*a0483764SConrad Meyer for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); 514*a0483764SConrad Meyer DISPLAY(" \n"); 515*a0483764SConrad Meyer DISPLAY("decode: "); 516*a0483764SConrad Meyer for (n=-5; n<0; n++) DISPLAY("%02X ", resultBuffer[u+n]); 517*a0483764SConrad Meyer DISPLAY(" :%02X: ", resultBuffer[u]); 518*a0483764SConrad Meyer for (n=1; n<3; n++) DISPLAY("%02X ", resultBuffer[u+n]); 519*a0483764SConrad Meyer DISPLAY(" \n"); 520*a0483764SConrad Meyer } 521*a0483764SConrad Meyer break; 522*a0483764SConrad Meyer } 523*a0483764SConrad Meyer if (u==srcSize-1) { /* should never happen */ 524*a0483764SConrad Meyer DISPLAY("no difference detected\n"); 525*a0483764SConrad Meyer } 526*a0483764SConrad Meyer } 527*a0483764SConrad Meyer } 528*a0483764SConrad Meyer } /* CRC Checking */ 529*a0483764SConrad Meyer 530*a0483764SConrad Meyer if (displayLevel == 1) { /* hidden display mode -q, used by python speed benchmark */ 531*a0483764SConrad Meyer double const cSpeed = (double)benchResult.cSpeed / MB_UNIT; 532*a0483764SConrad Meyer double const dSpeed = (double)benchResult.dSpeed / MB_UNIT; 533*a0483764SConrad Meyer if (adv->additionalParam) { 534*a0483764SConrad Meyer DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s (param=%d)\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName, adv->additionalParam); 535*a0483764SConrad Meyer } else { 536*a0483764SConrad Meyer DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName); 537*a0483764SConrad Meyer } 538*a0483764SConrad Meyer } 539*a0483764SConrad Meyer 540*a0483764SConrad Meyer DISPLAYLEVEL(2, "%2i#\n", cLevel); 541*a0483764SConrad Meyer } /* Bench */ 542*a0483764SConrad Meyer 543*a0483764SConrad Meyer benchResult.cMem = (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx); 544*a0483764SConrad Meyer return BMK_benchOutcome_setValidResult(benchResult); 545*a0483764SConrad Meyer } 546*a0483764SConrad Meyer 547*a0483764SConrad Meyer BMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize, 548*a0483764SConrad Meyer void* dstBuffer, size_t dstCapacity, 549*a0483764SConrad Meyer const size_t* fileSizes, unsigned nbFiles, 550*a0483764SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams, 551*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize, 552*a0483764SConrad Meyer int displayLevel, const char* displayName, const BMK_advancedParams_t* adv) 553*a0483764SConrad Meyer 554*a0483764SConrad Meyer { 555*a0483764SConrad Meyer int const dstParamsError = !dstBuffer ^ !dstCapacity; /* must be both NULL or none */ 556*a0483764SConrad Meyer 557*a0483764SConrad Meyer size_t const blockSize = ((adv->blockSize>=32 && (adv->mode != BMK_decodeOnly)) ? adv->blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ; 558*a0483764SConrad Meyer U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles; 559*a0483764SConrad Meyer 560*a0483764SConrad Meyer /* these are the blockTable parameters, just split up */ 561*a0483764SConrad Meyer const void ** const srcPtrs = (const void**)malloc(maxNbBlocks * sizeof(void*)); 562*a0483764SConrad Meyer size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 563*a0483764SConrad Meyer 564*a0483764SConrad Meyer 565*a0483764SConrad Meyer void ** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*)); 566*a0483764SConrad Meyer size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 567*a0483764SConrad Meyer size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 568*a0483764SConrad Meyer 569*a0483764SConrad Meyer void ** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*)); 570*a0483764SConrad Meyer size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t)); 571*a0483764SConrad Meyer 572*a0483764SConrad Meyer BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS); 573*a0483764SConrad Meyer BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS); 574*a0483764SConrad Meyer 575*a0483764SConrad Meyer ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 576*a0483764SConrad Meyer ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 577*a0483764SConrad Meyer 578*a0483764SConrad Meyer const size_t maxCompressedSize = dstCapacity ? dstCapacity : ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); 579*a0483764SConrad Meyer 580*a0483764SConrad Meyer void* const internalDstBuffer = dstBuffer ? NULL : malloc(maxCompressedSize); 581*a0483764SConrad Meyer void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer; 582*a0483764SConrad Meyer 583*a0483764SConrad Meyer BMK_benchOutcome_t outcome = BMK_benchOutcome_error(); /* error by default */ 584*a0483764SConrad Meyer 585*a0483764SConrad Meyer void* resultBuffer = srcSize ? malloc(srcSize) : NULL; 586*a0483764SConrad Meyer 587*a0483764SConrad Meyer int allocationincomplete = !srcPtrs || !srcSizes || !cPtrs || 588*a0483764SConrad Meyer !cSizes || !cCapacities || !resPtrs || !resSizes || 589*a0483764SConrad Meyer !timeStateCompress || !timeStateDecompress || 590*a0483764SConrad Meyer !cctx || !dctx || 591*a0483764SConrad Meyer !compressedBuffer || !resultBuffer; 592*a0483764SConrad Meyer 593*a0483764SConrad Meyer 594*a0483764SConrad Meyer if (!allocationincomplete && !dstParamsError) { 595*a0483764SConrad Meyer outcome = BMK_benchMemAdvancedNoAlloc(srcPtrs, srcSizes, 596*a0483764SConrad Meyer cPtrs, cCapacities, cSizes, 597*a0483764SConrad Meyer resPtrs, resSizes, 598*a0483764SConrad Meyer &resultBuffer, 599*a0483764SConrad Meyer compressedBuffer, maxCompressedSize, 600*a0483764SConrad Meyer timeStateCompress, timeStateDecompress, 601*a0483764SConrad Meyer srcBuffer, srcSize, 602*a0483764SConrad Meyer fileSizes, nbFiles, 603*a0483764SConrad Meyer cLevel, comprParams, 604*a0483764SConrad Meyer dictBuffer, dictBufferSize, 605*a0483764SConrad Meyer cctx, dctx, 606*a0483764SConrad Meyer displayLevel, displayName, adv); 607*a0483764SConrad Meyer } 608*a0483764SConrad Meyer 609*a0483764SConrad Meyer /* clean up */ 610*a0483764SConrad Meyer BMK_freeTimedFnState(timeStateCompress); 611*a0483764SConrad Meyer BMK_freeTimedFnState(timeStateDecompress); 612*a0483764SConrad Meyer 613*a0483764SConrad Meyer ZSTD_freeCCtx(cctx); 614*a0483764SConrad Meyer ZSTD_freeDCtx(dctx); 615*a0483764SConrad Meyer 616*a0483764SConrad Meyer free(internalDstBuffer); 617*a0483764SConrad Meyer free(resultBuffer); 618*a0483764SConrad Meyer 619*a0483764SConrad Meyer free((void*)srcPtrs); 620*a0483764SConrad Meyer free(srcSizes); 621*a0483764SConrad Meyer free(cPtrs); 622*a0483764SConrad Meyer free(cSizes); 623*a0483764SConrad Meyer free(cCapacities); 624*a0483764SConrad Meyer free(resPtrs); 625*a0483764SConrad Meyer free(resSizes); 626*a0483764SConrad Meyer 627*a0483764SConrad Meyer if(allocationincomplete) { 628*a0483764SConrad Meyer RETURN_ERROR(31, BMK_benchOutcome_t, "allocation error : not enough memory"); 629*a0483764SConrad Meyer } 630*a0483764SConrad Meyer 631*a0483764SConrad Meyer if(dstParamsError) { 632*a0483764SConrad Meyer RETURN_ERROR(32, BMK_benchOutcome_t, "Dst parameters not coherent"); 633*a0483764SConrad Meyer } 634*a0483764SConrad Meyer return outcome; 635*a0483764SConrad Meyer } 636*a0483764SConrad Meyer 637*a0483764SConrad Meyer BMK_benchOutcome_t BMK_benchMem(const void* srcBuffer, size_t srcSize, 638*a0483764SConrad Meyer const size_t* fileSizes, unsigned nbFiles, 639*a0483764SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams, 640*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize, 641*a0483764SConrad Meyer int displayLevel, const char* displayName) { 642*a0483764SConrad Meyer 643*a0483764SConrad Meyer BMK_advancedParams_t const adv = BMK_initAdvancedParams(); 644*a0483764SConrad Meyer return BMK_benchMemAdvanced(srcBuffer, srcSize, 645*a0483764SConrad Meyer NULL, 0, 646*a0483764SConrad Meyer fileSizes, nbFiles, 647*a0483764SConrad Meyer cLevel, comprParams, 648*a0483764SConrad Meyer dictBuffer, dictBufferSize, 649*a0483764SConrad Meyer displayLevel, displayName, &adv); 650*a0483764SConrad Meyer } 651*a0483764SConrad Meyer 652*a0483764SConrad Meyer static BMK_benchOutcome_t BMK_benchCLevel(const void* srcBuffer, size_t benchedSize, 653*a0483764SConrad Meyer const size_t* fileSizes, unsigned nbFiles, 654*a0483764SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams, 655*a0483764SConrad Meyer const void* dictBuffer, size_t dictBufferSize, 656*a0483764SConrad Meyer int displayLevel, const char* displayName, 657*a0483764SConrad Meyer BMK_advancedParams_t const * const adv) 658*a0483764SConrad Meyer { 659*a0483764SConrad Meyer const char* pch = strrchr(displayName, '\\'); /* Windows */ 660*a0483764SConrad Meyer if (!pch) pch = strrchr(displayName, '/'); /* Linux */ 661*a0483764SConrad Meyer if (pch) displayName = pch+1; 662*a0483764SConrad Meyer 663*a0483764SConrad Meyer if (adv->realTime) { 664*a0483764SConrad Meyer DISPLAYLEVEL(2, "Note : switching to real-time priority \n"); 665*a0483764SConrad Meyer SET_REALTIME_PRIORITY; 666*a0483764SConrad Meyer } 667*a0483764SConrad Meyer 668*a0483764SConrad Meyer if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */ 669*a0483764SConrad Meyer DISPLAY("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n", 670*a0483764SConrad Meyer ZSTD_VERSION_STRING, ZSTD_GIT_COMMIT_STRING, 671*a0483764SConrad Meyer (unsigned)benchedSize, adv->nbSeconds, (unsigned)(adv->blockSize>>10)); 672*a0483764SConrad Meyer 673*a0483764SConrad Meyer return BMK_benchMemAdvanced(srcBuffer, benchedSize, 674*a0483764SConrad Meyer NULL, 0, 675*a0483764SConrad Meyer fileSizes, nbFiles, 676*a0483764SConrad Meyer cLevel, comprParams, 677*a0483764SConrad Meyer dictBuffer, dictBufferSize, 678*a0483764SConrad Meyer displayLevel, displayName, adv); 679*a0483764SConrad Meyer } 680*a0483764SConrad Meyer 681*a0483764SConrad Meyer BMK_benchOutcome_t BMK_syntheticTest(int cLevel, double compressibility, 682*a0483764SConrad Meyer const ZSTD_compressionParameters* compressionParams, 683*a0483764SConrad Meyer int displayLevel, const BMK_advancedParams_t* adv) 684*a0483764SConrad Meyer { 685*a0483764SConrad Meyer char name[20] = {0}; 686*a0483764SConrad Meyer size_t const benchedSize = 10000000; 687*a0483764SConrad Meyer void* srcBuffer; 688*a0483764SConrad Meyer BMK_benchOutcome_t res; 689*a0483764SConrad Meyer 690*a0483764SConrad Meyer if (cLevel > ZSTD_maxCLevel()) { 691*a0483764SConrad Meyer RETURN_ERROR(15, BMK_benchOutcome_t, "Invalid Compression Level"); 692*a0483764SConrad Meyer } 693*a0483764SConrad Meyer 694*a0483764SConrad Meyer /* Memory allocation */ 695*a0483764SConrad Meyer srcBuffer = malloc(benchedSize); 696*a0483764SConrad Meyer if (!srcBuffer) RETURN_ERROR(21, BMK_benchOutcome_t, "not enough memory"); 697*a0483764SConrad Meyer 698*a0483764SConrad Meyer /* Fill input buffer */ 699*a0483764SConrad Meyer RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0); 700*a0483764SConrad Meyer 701*a0483764SConrad Meyer /* Bench */ 702*a0483764SConrad Meyer snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100)); 703*a0483764SConrad Meyer res = BMK_benchCLevel(srcBuffer, benchedSize, 704*a0483764SConrad Meyer &benchedSize /* ? */, 1 /* ? */, 705*a0483764SConrad Meyer cLevel, compressionParams, 706*a0483764SConrad Meyer NULL, 0, /* dictionary */ 707*a0483764SConrad Meyer displayLevel, name, adv); 708*a0483764SConrad Meyer 709*a0483764SConrad Meyer /* clean up */ 710*a0483764SConrad Meyer free(srcBuffer); 711*a0483764SConrad Meyer 712*a0483764SConrad Meyer return res; 713*a0483764SConrad Meyer } 714*a0483764SConrad Meyer 715*a0483764SConrad Meyer 716*a0483764SConrad Meyer 717*a0483764SConrad Meyer static size_t BMK_findMaxMem(U64 requiredMem) 718*a0483764SConrad Meyer { 719*a0483764SConrad Meyer size_t const step = 64 MB; 720*a0483764SConrad Meyer BYTE* testmem = NULL; 721*a0483764SConrad Meyer 722*a0483764SConrad Meyer requiredMem = (((requiredMem >> 26) + 1) << 26); 723*a0483764SConrad Meyer requiredMem += step; 724*a0483764SConrad Meyer if (requiredMem > maxMemory) requiredMem = maxMemory; 725*a0483764SConrad Meyer 726*a0483764SConrad Meyer do { 727*a0483764SConrad Meyer testmem = (BYTE*)malloc((size_t)requiredMem); 728*a0483764SConrad Meyer requiredMem -= step; 729*a0483764SConrad Meyer } while (!testmem && requiredMem > 0); 730*a0483764SConrad Meyer 731*a0483764SConrad Meyer free(testmem); 732*a0483764SConrad Meyer return (size_t)(requiredMem); 733*a0483764SConrad Meyer } 734*a0483764SConrad Meyer 735*a0483764SConrad Meyer /*! BMK_loadFiles() : 736*a0483764SConrad Meyer * Loads `buffer` with content of files listed within `fileNamesTable`. 737*a0483764SConrad Meyer * At most, fills `buffer` entirely. */ 738*a0483764SConrad Meyer static int BMK_loadFiles(void* buffer, size_t bufferSize, 739*a0483764SConrad Meyer size_t* fileSizes, 740*a0483764SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles, 741*a0483764SConrad Meyer int displayLevel) 742*a0483764SConrad Meyer { 743*a0483764SConrad Meyer size_t pos = 0, totalSize = 0; 744*a0483764SConrad Meyer unsigned n; 745*a0483764SConrad Meyer for (n=0; n<nbFiles; n++) { 746*a0483764SConrad Meyer FILE* f; 747*a0483764SConrad Meyer U64 fileSize = UTIL_getFileSize(fileNamesTable[n]); 748*a0483764SConrad Meyer if (UTIL_isDirectory(fileNamesTable[n])) { 749*a0483764SConrad Meyer DISPLAYLEVEL(2, "Ignoring %s directory... \n", fileNamesTable[n]); 750*a0483764SConrad Meyer fileSizes[n] = 0; 751*a0483764SConrad Meyer continue; 752*a0483764SConrad Meyer } 753*a0483764SConrad Meyer if (fileSize == UTIL_FILESIZE_UNKNOWN) { 754*a0483764SConrad Meyer DISPLAYLEVEL(2, "Cannot evaluate size of %s, ignoring ... \n", fileNamesTable[n]); 755*a0483764SConrad Meyer fileSizes[n] = 0; 756*a0483764SConrad Meyer continue; 757*a0483764SConrad Meyer } 758*a0483764SConrad Meyer f = fopen(fileNamesTable[n], "rb"); 759*a0483764SConrad Meyer if (f==NULL) EXM_THROW_INT(10, "impossible to open file %s", fileNamesTable[n]); 760*a0483764SConrad Meyer DISPLAYUPDATE(2, "Loading %s... \r", fileNamesTable[n]); 761*a0483764SConrad Meyer if (fileSize > bufferSize-pos) fileSize = bufferSize-pos, nbFiles=n; /* buffer too small - stop after this file */ 762*a0483764SConrad Meyer { size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f); 763*a0483764SConrad Meyer if (readSize != (size_t)fileSize) EXM_THROW_INT(11, "could not read %s", fileNamesTable[n]); 764*a0483764SConrad Meyer pos += readSize; 765*a0483764SConrad Meyer } 766*a0483764SConrad Meyer fileSizes[n] = (size_t)fileSize; 767*a0483764SConrad Meyer totalSize += (size_t)fileSize; 768*a0483764SConrad Meyer fclose(f); 769*a0483764SConrad Meyer } 770*a0483764SConrad Meyer 771*a0483764SConrad Meyer if (totalSize == 0) EXM_THROW_INT(12, "no data to bench"); 772*a0483764SConrad Meyer return 0; 773*a0483764SConrad Meyer } 774*a0483764SConrad Meyer 775*a0483764SConrad Meyer BMK_benchOutcome_t BMK_benchFilesAdvanced( 776*a0483764SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles, 777*a0483764SConrad Meyer const char* dictFileName, int cLevel, 778*a0483764SConrad Meyer const ZSTD_compressionParameters* compressionParams, 779*a0483764SConrad Meyer int displayLevel, const BMK_advancedParams_t* adv) 780*a0483764SConrad Meyer { 781*a0483764SConrad Meyer void* srcBuffer = NULL; 782*a0483764SConrad Meyer size_t benchedSize; 783*a0483764SConrad Meyer void* dictBuffer = NULL; 784*a0483764SConrad Meyer size_t dictBufferSize = 0; 785*a0483764SConrad Meyer size_t* fileSizes = NULL; 786*a0483764SConrad Meyer BMK_benchOutcome_t res; 787*a0483764SConrad Meyer U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles); 788*a0483764SConrad Meyer 789*a0483764SConrad Meyer if (!nbFiles) { 790*a0483764SConrad Meyer RETURN_ERROR(14, BMK_benchOutcome_t, "No Files to Benchmark"); 791*a0483764SConrad Meyer } 792*a0483764SConrad Meyer 793*a0483764SConrad Meyer if (cLevel > ZSTD_maxCLevel()) { 794*a0483764SConrad Meyer RETURN_ERROR(15, BMK_benchOutcome_t, "Invalid Compression Level"); 795*a0483764SConrad Meyer } 796*a0483764SConrad Meyer 797*a0483764SConrad Meyer fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t)); 798*a0483764SConrad Meyer if (!fileSizes) RETURN_ERROR(12, BMK_benchOutcome_t, "not enough memory for fileSizes"); 799*a0483764SConrad Meyer 800*a0483764SConrad Meyer /* Load dictionary */ 801*a0483764SConrad Meyer if (dictFileName != NULL) { 802*a0483764SConrad Meyer U64 const dictFileSize = UTIL_getFileSize(dictFileName); 803*a0483764SConrad Meyer if (dictFileSize == UTIL_FILESIZE_UNKNOWN) { 804*a0483764SConrad Meyer DISPLAYLEVEL(1, "error loading %s : %s \n", dictFileName, strerror(errno)); 805*a0483764SConrad Meyer free(fileSizes); 806*a0483764SConrad Meyer RETURN_ERROR(9, BMK_benchOutcome_t, "benchmark aborted"); 807*a0483764SConrad Meyer } 808*a0483764SConrad Meyer if (dictFileSize > 64 MB) { 809*a0483764SConrad Meyer free(fileSizes); 810*a0483764SConrad Meyer RETURN_ERROR(10, BMK_benchOutcome_t, "dictionary file %s too large", dictFileName); 811*a0483764SConrad Meyer } 812*a0483764SConrad Meyer dictBufferSize = (size_t)dictFileSize; 813*a0483764SConrad Meyer dictBuffer = malloc(dictBufferSize); 814*a0483764SConrad Meyer if (dictBuffer==NULL) { 815*a0483764SConrad Meyer free(fileSizes); 816*a0483764SConrad Meyer RETURN_ERROR(11, BMK_benchOutcome_t, "not enough memory for dictionary (%u bytes)", 817*a0483764SConrad Meyer (unsigned)dictBufferSize); 818*a0483764SConrad Meyer } 819*a0483764SConrad Meyer 820*a0483764SConrad Meyer { int const errorCode = BMK_loadFiles(dictBuffer, dictBufferSize, 821*a0483764SConrad Meyer fileSizes, &dictFileName /*?*/, 822*a0483764SConrad Meyer 1 /*?*/, displayLevel); 823*a0483764SConrad Meyer if (errorCode) { 824*a0483764SConrad Meyer res = BMK_benchOutcome_error(); 825*a0483764SConrad Meyer goto _cleanUp; 826*a0483764SConrad Meyer } } 827*a0483764SConrad Meyer } 828*a0483764SConrad Meyer 829*a0483764SConrad Meyer /* Memory allocation & restrictions */ 830*a0483764SConrad Meyer benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3; 831*a0483764SConrad Meyer if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad; 832*a0483764SConrad Meyer if (benchedSize < totalSizeToLoad) 833*a0483764SConrad Meyer DISPLAY("Not enough memory; testing %u MB only...\n", (unsigned)(benchedSize >> 20)); 834*a0483764SConrad Meyer 835*a0483764SConrad Meyer srcBuffer = benchedSize ? malloc(benchedSize) : NULL; 836*a0483764SConrad Meyer if (!srcBuffer) { 837*a0483764SConrad Meyer free(dictBuffer); 838*a0483764SConrad Meyer free(fileSizes); 839*a0483764SConrad Meyer RETURN_ERROR(12, BMK_benchOutcome_t, "not enough memory"); 840*a0483764SConrad Meyer } 841*a0483764SConrad Meyer 842*a0483764SConrad Meyer /* Load input buffer */ 843*a0483764SConrad Meyer { int const errorCode = BMK_loadFiles(srcBuffer, benchedSize, 844*a0483764SConrad Meyer fileSizes, fileNamesTable, nbFiles, 845*a0483764SConrad Meyer displayLevel); 846*a0483764SConrad Meyer if (errorCode) { 847*a0483764SConrad Meyer res = BMK_benchOutcome_error(); 848*a0483764SConrad Meyer goto _cleanUp; 849*a0483764SConrad Meyer } } 850*a0483764SConrad Meyer 851*a0483764SConrad Meyer /* Bench */ 852*a0483764SConrad Meyer { char mfName[20] = {0}; 853*a0483764SConrad Meyer snprintf (mfName, sizeof(mfName), " %u files", nbFiles); 854*a0483764SConrad Meyer { const char* const displayName = (nbFiles > 1) ? mfName : fileNamesTable[0]; 855*a0483764SConrad Meyer res = BMK_benchCLevel(srcBuffer, benchedSize, 856*a0483764SConrad Meyer fileSizes, nbFiles, 857*a0483764SConrad Meyer cLevel, compressionParams, 858*a0483764SConrad Meyer dictBuffer, dictBufferSize, 859*a0483764SConrad Meyer displayLevel, displayName, 860*a0483764SConrad Meyer adv); 861*a0483764SConrad Meyer } } 862*a0483764SConrad Meyer 863*a0483764SConrad Meyer _cleanUp: 864*a0483764SConrad Meyer free(srcBuffer); 865*a0483764SConrad Meyer free(dictBuffer); 866*a0483764SConrad Meyer free(fileSizes); 867*a0483764SConrad Meyer return res; 868*a0483764SConrad Meyer } 869*a0483764SConrad Meyer 870*a0483764SConrad Meyer 871*a0483764SConrad Meyer BMK_benchOutcome_t BMK_benchFiles( 872*a0483764SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles, 873*a0483764SConrad Meyer const char* dictFileName, 874*a0483764SConrad Meyer int cLevel, const ZSTD_compressionParameters* compressionParams, 875*a0483764SConrad Meyer int displayLevel) 876*a0483764SConrad Meyer { 877*a0483764SConrad Meyer BMK_advancedParams_t const adv = BMK_initAdvancedParams(); 878*a0483764SConrad Meyer return BMK_benchFilesAdvanced(fileNamesTable, nbFiles, dictFileName, cLevel, compressionParams, displayLevel, &adv); 879*a0483764SConrad Meyer } 880