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