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