1902c8ce7SBaptiste Daroussin /*
2b3392d84SAllan Jude * Copyright (c) Yann Collet, Facebook, Inc.
3a19eddc3SBaptiste Daroussin * All rights reserved.
4a19eddc3SBaptiste Daroussin *
5902c8ce7SBaptiste Daroussin * This source code is licensed under both the BSD-style license (found in the
6902c8ce7SBaptiste Daroussin * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7902c8ce7SBaptiste Daroussin * in the COPYING file in the root directory of this source tree).
8653667f9SBaptiste Daroussin * You may select, at your option, one of the above-listed licenses.
9a19eddc3SBaptiste Daroussin */
10a19eddc3SBaptiste Daroussin
11a19eddc3SBaptiste Daroussin
12a19eddc3SBaptiste Daroussin /* **************************************
13a19eddc3SBaptiste Daroussin * Tuning parameters
14a19eddc3SBaptiste Daroussin ****************************************/
15a19eddc3SBaptiste Daroussin #ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */
16a19eddc3SBaptiste Daroussin #define BMK_TIMETEST_DEFAULT_S 3
17a19eddc3SBaptiste Daroussin #endif
18a19eddc3SBaptiste Daroussin
19a19eddc3SBaptiste Daroussin
20a19eddc3SBaptiste Daroussin /* *************************************
21a19eddc3SBaptiste Daroussin * Includes
22a19eddc3SBaptiste Daroussin ***************************************/
23a19eddc3SBaptiste Daroussin #include "platform.h" /* Large Files support */
24a19eddc3SBaptiste Daroussin #include "util.h" /* UTIL_getFileSize, UTIL_sleep */
25a19eddc3SBaptiste Daroussin #include <stdlib.h> /* malloc, free */
26af73257bSConrad Meyer #include <string.h> /* memset, strerror */
27a19eddc3SBaptiste Daroussin #include <stdio.h> /* fprintf, fopen */
28af73257bSConrad Meyer #include <errno.h>
2942239e68SConrad Meyer #include <assert.h> /* assert */
30a19eddc3SBaptiste Daroussin
313f774a5eSConrad Meyer #include "timefn.h" /* UTIL_time_t */
32af73257bSConrad Meyer #include "benchfn.h"
33bc64b5ceSConrad Meyer #include "../lib/common/mem.h"
34b3392d84SAllan Jude #ifndef ZSTD_STATIC_LINKING_ONLY
35a19eddc3SBaptiste Daroussin #define ZSTD_STATIC_LINKING_ONLY
36b3392d84SAllan Jude #endif
37bc64b5ceSConrad Meyer #include "../lib/zstd.h"
38a19eddc3SBaptiste Daroussin #include "datagen.h" /* RDG_genBuffer */
39b3392d84SAllan Jude #ifndef XXH_INLINE_ALL
40b3392d84SAllan Jude #define XXH_INLINE_ALL
41b3392d84SAllan Jude #endif
42bc64b5ceSConrad Meyer #include "../lib/common/xxhash.h"
43af73257bSConrad Meyer #include "benchzstd.h"
44b3392d84SAllan Jude #include "../lib/zstd_errors.h"
45a19eddc3SBaptiste Daroussin
46a19eddc3SBaptiste Daroussin
47a19eddc3SBaptiste Daroussin /* *************************************
48a19eddc3SBaptiste Daroussin * Constants
49a19eddc3SBaptiste Daroussin ***************************************/
50a19eddc3SBaptiste Daroussin #ifndef ZSTD_GIT_COMMIT
51a19eddc3SBaptiste Daroussin # define ZSTD_GIT_COMMIT_STRING ""
52a19eddc3SBaptiste Daroussin #else
53a19eddc3SBaptiste Daroussin # define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)
54a19eddc3SBaptiste Daroussin #endif
55a19eddc3SBaptiste Daroussin
5642239e68SConrad Meyer #define TIMELOOP_MICROSEC (1*1000000ULL) /* 1 second */
5742239e68SConrad Meyer #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
5842239e68SConrad Meyer #define ACTIVEPERIOD_MICROSEC (70*TIMELOOP_MICROSEC) /* 70 seconds */
59a19eddc3SBaptiste Daroussin #define COOLPERIOD_SEC 10
60a19eddc3SBaptiste Daroussin
61a19eddc3SBaptiste Daroussin #define KB *(1 <<10)
62a19eddc3SBaptiste Daroussin #define MB *(1 <<20)
63a19eddc3SBaptiste Daroussin #define GB *(1U<<30)
64a19eddc3SBaptiste Daroussin
65706cfae4SConrad Meyer #define BMK_RUNTEST_DEFAULT_MS 1000
66a19eddc3SBaptiste Daroussin
67706cfae4SConrad Meyer static const size_t maxMemory = (sizeof(size_t)==4) ?
68706cfae4SConrad Meyer /* 32-bit */ (2 GB - 64 MB) :
69706cfae4SConrad Meyer /* 64-bit */ (size_t)(1ULL << ((sizeof(size_t)*8)-31));
70a19eddc3SBaptiste Daroussin
71a19eddc3SBaptiste Daroussin
72a19eddc3SBaptiste Daroussin /* *************************************
73a19eddc3SBaptiste Daroussin * console display
74a19eddc3SBaptiste Daroussin ***************************************/
75b3392d84SAllan Jude #define DISPLAY(...) { fprintf(stderr, __VA_ARGS__); fflush(NULL); }
76706cfae4SConrad Meyer #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
77706cfae4SConrad Meyer /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */
78b3392d84SAllan Jude #define OUTPUT(...) { fprintf(stdout, __VA_ARGS__); fflush(NULL); }
79b3392d84SAllan Jude #define OUTPUTLEVEL(l, ...) if (displayLevel>=l) { OUTPUT(__VA_ARGS__); }
80a19eddc3SBaptiste Daroussin
81a19eddc3SBaptiste Daroussin
82a19eddc3SBaptiste Daroussin /* *************************************
83a19eddc3SBaptiste Daroussin * Exceptions
84a19eddc3SBaptiste Daroussin ***************************************/
85a19eddc3SBaptiste Daroussin #ifndef DEBUG
86a19eddc3SBaptiste Daroussin # define DEBUG 0
87a19eddc3SBaptiste Daroussin #endif
88affe9eafSBaptiste Daroussin #define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }
89706cfae4SConrad Meyer
90ea684039SConrad Meyer #define RETURN_ERROR_INT(errorNum, ...) { \
91ffcbc2d7SBaptiste Daroussin DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
92706cfae4SConrad Meyer DISPLAYLEVEL(1, "Error %i : ", errorNum); \
93a19eddc3SBaptiste Daroussin DISPLAYLEVEL(1, __VA_ARGS__); \
94a19eddc3SBaptiste Daroussin DISPLAYLEVEL(1, " \n"); \
95706cfae4SConrad Meyer return errorNum; \
96a19eddc3SBaptiste Daroussin }
97a19eddc3SBaptiste Daroussin
98af73257bSConrad Meyer #define CHECK_Z(zf) { \
99af73257bSConrad Meyer size_t const zerr = zf; \
100af73257bSConrad Meyer if (ZSTD_isError(zerr)) { \
101af73257bSConrad Meyer DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
102af73257bSConrad Meyer DISPLAY("Error : "); \
103af73257bSConrad Meyer DISPLAY("%s failed : %s", \
104af73257bSConrad Meyer #zf, ZSTD_getErrorName(zerr)); \
105af73257bSConrad Meyer DISPLAY(" \n"); \
106af73257bSConrad Meyer exit(1); \
107af73257bSConrad Meyer } \
108af73257bSConrad Meyer }
109af73257bSConrad Meyer
110706cfae4SConrad Meyer #define RETURN_ERROR(errorNum, retType, ...) { \
111706cfae4SConrad Meyer retType r; \
112706cfae4SConrad Meyer memset(&r, 0, sizeof(retType)); \
113706cfae4SConrad Meyer DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
114706cfae4SConrad Meyer DISPLAYLEVEL(1, "Error %i : ", errorNum); \
115706cfae4SConrad Meyer DISPLAYLEVEL(1, __VA_ARGS__); \
116706cfae4SConrad Meyer DISPLAYLEVEL(1, " \n"); \
117706cfae4SConrad Meyer r.tag = errorNum; \
118706cfae4SConrad Meyer return r; \
119706cfae4SConrad Meyer }
120706cfae4SConrad Meyer
121a19eddc3SBaptiste Daroussin
122a19eddc3SBaptiste Daroussin /* *************************************
123a19eddc3SBaptiste Daroussin * Benchmark Parameters
124a19eddc3SBaptiste Daroussin ***************************************/
125a19eddc3SBaptiste Daroussin
BMK_initAdvancedParams(void)126706cfae4SConrad Meyer BMK_advancedParams_t BMK_initAdvancedParams(void) {
127706cfae4SConrad Meyer BMK_advancedParams_t const res = {
128706cfae4SConrad Meyer BMK_both, /* mode */
129706cfae4SConrad Meyer BMK_TIMETEST_DEFAULT_S, /* nbSeconds */
130706cfae4SConrad Meyer 0, /* blockSize */
131706cfae4SConrad Meyer 0, /* nbWorkers */
132706cfae4SConrad Meyer 0, /* realTime */
133706cfae4SConrad Meyer 0, /* additionalParam */
134706cfae4SConrad Meyer 0, /* ldmFlag */
135706cfae4SConrad Meyer 0, /* ldmMinMatch */
136706cfae4SConrad Meyer 0, /* ldmHashLog */
137706cfae4SConrad Meyer 0, /* ldmBuckSizeLog */
1383f774a5eSConrad Meyer 0, /* ldmHashRateLog */
139b3392d84SAllan Jude ZSTD_ps_auto, /* literalCompressionMode */
140b3392d84SAllan Jude 0 /* useRowMatchFinder */
141706cfae4SConrad Meyer };
142706cfae4SConrad Meyer return res;
143653667f9SBaptiste Daroussin }
144a19eddc3SBaptiste Daroussin
145a19eddc3SBaptiste Daroussin
146a19eddc3SBaptiste Daroussin /* ********************************************************
147a19eddc3SBaptiste Daroussin * Bench functions
148a19eddc3SBaptiste Daroussin **********************************************************/
149a19eddc3SBaptiste Daroussin typedef struct {
150a19eddc3SBaptiste Daroussin const void* srcPtr;
151a19eddc3SBaptiste Daroussin size_t srcSize;
152a19eddc3SBaptiste Daroussin void* cPtr;
153a19eddc3SBaptiste Daroussin size_t cRoom;
154a19eddc3SBaptiste Daroussin size_t cSize;
155a19eddc3SBaptiste Daroussin void* resPtr;
156a19eddc3SBaptiste Daroussin size_t resSize;
157a19eddc3SBaptiste Daroussin } blockParam_t;
158a19eddc3SBaptiste Daroussin
159ffcbc2d7SBaptiste Daroussin #undef MIN
160ffcbc2d7SBaptiste Daroussin #undef MAX
161a19eddc3SBaptiste Daroussin #define MIN(a,b) ((a) < (b) ? (a) : (b))
162a19eddc3SBaptiste Daroussin #define MAX(a,b) ((a) > (b) ? (a) : (b))
163a19eddc3SBaptiste Daroussin
1643f774a5eSConrad 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)1653f774a5eSConrad Meyer BMK_initCCtx(ZSTD_CCtx* ctx,
1663f774a5eSConrad Meyer const void* dictBuffer, size_t dictBufferSize,
1673f774a5eSConrad Meyer int cLevel,
1683f774a5eSConrad Meyer const ZSTD_compressionParameters* comprParams,
1693f774a5eSConrad Meyer const BMK_advancedParams_t* adv)
1703f774a5eSConrad Meyer {
171af73257bSConrad Meyer ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);
172706cfae4SConrad Meyer if (adv->nbWorkers==1) {
173af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));
17442239e68SConrad Meyer } else {
175af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers));
17642239e68SConrad Meyer }
177af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel));
178b3392d84SAllan Jude CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_useRowMatchFinder, adv->useRowMatchFinder));
179af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag));
180af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch));
181af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));
182af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));
183af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));
1843f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));
1853f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));
1863f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));
1873f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));
1883f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));
1893f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));
1903f774a5eSConrad Meyer CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_literalCompressionMode, (int)adv->literalCompressionMode));
191b3392d84SAllan Jude CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, (int)comprParams->strategy));
192af73257bSConrad Meyer CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));
193706cfae4SConrad Meyer }
19442239e68SConrad Meyer
BMK_initDCtx(ZSTD_DCtx * dctx,const void * dictBuffer,size_t dictBufferSize)195706cfae4SConrad Meyer static void BMK_initDCtx(ZSTD_DCtx* dctx,
196706cfae4SConrad Meyer const void* dictBuffer, size_t dictBufferSize) {
197af73257bSConrad Meyer CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));
198af73257bSConrad Meyer CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize));
199706cfae4SConrad Meyer }
200706cfae4SConrad Meyer
201706cfae4SConrad Meyer
202706cfae4SConrad Meyer typedef struct {
203706cfae4SConrad Meyer ZSTD_CCtx* cctx;
204706cfae4SConrad Meyer const void* dictBuffer;
205706cfae4SConrad Meyer size_t dictBufferSize;
206706cfae4SConrad Meyer int cLevel;
207706cfae4SConrad Meyer const ZSTD_compressionParameters* comprParams;
208706cfae4SConrad Meyer const BMK_advancedParams_t* adv;
209706cfae4SConrad Meyer } BMK_initCCtxArgs;
210706cfae4SConrad Meyer
local_initCCtx(void * payload)211706cfae4SConrad Meyer static size_t local_initCCtx(void* payload) {
212706cfae4SConrad Meyer BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload;
213706cfae4SConrad Meyer BMK_initCCtx(ag->cctx, ag->dictBuffer, ag->dictBufferSize, ag->cLevel, ag->comprParams, ag->adv);
214706cfae4SConrad Meyer return 0;
215706cfae4SConrad Meyer }
216706cfae4SConrad Meyer
217706cfae4SConrad Meyer typedef struct {
218706cfae4SConrad Meyer ZSTD_DCtx* dctx;
219706cfae4SConrad Meyer const void* dictBuffer;
220706cfae4SConrad Meyer size_t dictBufferSize;
221706cfae4SConrad Meyer } BMK_initDCtxArgs;
222706cfae4SConrad Meyer
local_initDCtx(void * payload)223706cfae4SConrad Meyer static size_t local_initDCtx(void* payload) {
224706cfae4SConrad Meyer BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload;
225706cfae4SConrad Meyer BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize);
226706cfae4SConrad Meyer return 0;
227706cfae4SConrad Meyer }
228706cfae4SConrad Meyer
229706cfae4SConrad Meyer
230706cfae4SConrad Meyer /* `addArgs` is the context */
local_defaultCompress(const void * srcBuffer,size_t srcSize,void * dstBuffer,size_t dstSize,void * addArgs)231706cfae4SConrad Meyer static size_t local_defaultCompress(
232706cfae4SConrad Meyer const void* srcBuffer, size_t srcSize,
233706cfae4SConrad Meyer void* dstBuffer, size_t dstSize,
234706cfae4SConrad Meyer void* addArgs)
235706cfae4SConrad Meyer {
236706cfae4SConrad Meyer ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs;
237af73257bSConrad Meyer return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize);
238706cfae4SConrad Meyer }
239a19eddc3SBaptiste Daroussin
240706cfae4SConrad Meyer /* `addArgs` is the context */
local_defaultDecompress(const void * srcBuffer,size_t srcSize,void * dstBuffer,size_t dstCapacity,void * addArgs)241706cfae4SConrad Meyer static size_t local_defaultDecompress(
242706cfae4SConrad Meyer const void* srcBuffer, size_t srcSize,
243706cfae4SConrad Meyer void* dstBuffer, size_t dstCapacity,
244706cfae4SConrad Meyer void* addArgs)
245706cfae4SConrad Meyer {
246706cfae4SConrad Meyer size_t moreToFlush = 1;
247706cfae4SConrad Meyer ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs;
248706cfae4SConrad Meyer ZSTD_inBuffer in;
249706cfae4SConrad Meyer ZSTD_outBuffer out;
250706cfae4SConrad Meyer in.src = srcBuffer; in.size = srcSize; in.pos = 0;
251706cfae4SConrad Meyer out.dst = dstBuffer; out.size = dstCapacity; out.pos = 0;
252706cfae4SConrad Meyer while (moreToFlush) {
253706cfae4SConrad Meyer if(out.pos == out.size) {
254706cfae4SConrad Meyer return (size_t)-ZSTD_error_dstSize_tooSmall;
255706cfae4SConrad Meyer }
256af73257bSConrad Meyer moreToFlush = ZSTD_decompressStream(dctx, &out, &in);
257706cfae4SConrad Meyer if (ZSTD_isError(moreToFlush)) {
258706cfae4SConrad Meyer return moreToFlush;
259706cfae4SConrad Meyer }
260706cfae4SConrad Meyer }
261706cfae4SConrad Meyer return out.pos;
262a19eddc3SBaptiste Daroussin
263706cfae4SConrad Meyer }
264706cfae4SConrad Meyer
265706cfae4SConrad Meyer
266706cfae4SConrad Meyer /* ================================================================= */
267706cfae4SConrad Meyer /* Benchmark Zstandard, mem-to-mem scenarios */
268706cfae4SConrad Meyer /* ================================================================= */
269706cfae4SConrad Meyer
BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome)270706cfae4SConrad Meyer int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome)
271706cfae4SConrad Meyer {
272706cfae4SConrad Meyer return outcome.tag == 0;
273706cfae4SConrad Meyer }
274706cfae4SConrad Meyer
BMK_extract_benchResult(BMK_benchOutcome_t outcome)275706cfae4SConrad Meyer BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome)
276706cfae4SConrad Meyer {
277706cfae4SConrad Meyer assert(outcome.tag == 0);
278706cfae4SConrad Meyer return outcome.internal_never_use_directly;
279706cfae4SConrad Meyer }
280706cfae4SConrad Meyer
BMK_benchOutcome_error(void)281706cfae4SConrad Meyer static BMK_benchOutcome_t BMK_benchOutcome_error(void)
282706cfae4SConrad Meyer {
283706cfae4SConrad Meyer BMK_benchOutcome_t b;
284706cfae4SConrad Meyer memset(&b, 0, sizeof(b));
285706cfae4SConrad Meyer b.tag = 1;
286706cfae4SConrad Meyer return b;
287706cfae4SConrad Meyer }
288706cfae4SConrad Meyer
BMK_benchOutcome_setValidResult(BMK_benchResult_t result)289706cfae4SConrad Meyer static BMK_benchOutcome_t BMK_benchOutcome_setValidResult(BMK_benchResult_t result)
290706cfae4SConrad Meyer {
291706cfae4SConrad Meyer BMK_benchOutcome_t b;
292706cfae4SConrad Meyer b.tag = 0;
293706cfae4SConrad Meyer b.internal_never_use_directly = result;
294706cfae4SConrad Meyer return b;
295706cfae4SConrad Meyer }
296706cfae4SConrad Meyer
297706cfae4SConrad Meyer
298706cfae4SConrad Meyer /* benchMem with no allocation */
299af73257bSConrad 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)300af73257bSConrad Meyer BMK_benchMemAdvancedNoAlloc(
301706cfae4SConrad Meyer const void** srcPtrs, size_t* srcSizes,
302706cfae4SConrad Meyer void** cPtrs, size_t* cCapacities, size_t* cSizes,
303706cfae4SConrad Meyer void** resPtrs, size_t* resSizes,
304706cfae4SConrad Meyer void** resultBufferPtr, void* compressedBuffer,
305706cfae4SConrad Meyer size_t maxCompressedSize,
306706cfae4SConrad Meyer BMK_timedFnState_t* timeStateCompress,
307706cfae4SConrad Meyer BMK_timedFnState_t* timeStateDecompress,
308706cfae4SConrad Meyer
309706cfae4SConrad Meyer const void* srcBuffer, size_t srcSize,
310706cfae4SConrad Meyer const size_t* fileSizes, unsigned nbFiles,
311af73257bSConrad Meyer const int cLevel,
312af73257bSConrad Meyer const ZSTD_compressionParameters* comprParams,
313706cfae4SConrad Meyer const void* dictBuffer, size_t dictBufferSize,
314706cfae4SConrad Meyer ZSTD_CCtx* cctx, ZSTD_DCtx* dctx,
315706cfae4SConrad Meyer int displayLevel, const char* displayName,
316706cfae4SConrad Meyer const BMK_advancedParams_t* adv)
317706cfae4SConrad Meyer {
318706cfae4SConrad Meyer size_t const blockSize = ((adv->blockSize>=32 && (adv->mode != BMK_decodeOnly)) ? adv->blockSize : srcSize) + (!srcSize); /* avoid div by 0 */
319706cfae4SConrad Meyer BMK_benchResult_t benchResult;
320706cfae4SConrad Meyer size_t const loadedCompressedSize = srcSize;
321706cfae4SConrad Meyer size_t cSize = 0;
322706cfae4SConrad Meyer double ratio = 0.;
323706cfae4SConrad Meyer U32 nbBlocks;
324706cfae4SConrad Meyer
325706cfae4SConrad Meyer assert(cctx != NULL); assert(dctx != NULL);
326706cfae4SConrad Meyer
327706cfae4SConrad Meyer /* init */
328706cfae4SConrad Meyer memset(&benchResult, 0, sizeof(benchResult));
329706cfae4SConrad Meyer if (strlen(displayName)>17) displayName += strlen(displayName) - 17; /* display last 17 characters */
330706cfae4SConrad Meyer if (adv->mode == BMK_decodeOnly) { /* benchmark only decompression : source must be already compressed */
331706cfae4SConrad Meyer const char* srcPtr = (const char*)srcBuffer;
332706cfae4SConrad Meyer U64 totalDSize64 = 0;
333706cfae4SConrad Meyer U32 fileNb;
334706cfae4SConrad Meyer for (fileNb=0; fileNb<nbFiles; fileNb++) {
335706cfae4SConrad Meyer U64 const fSize64 = ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]);
336706cfae4SConrad Meyer if (fSize64==0) RETURN_ERROR(32, BMK_benchOutcome_t, "Impossible to determine original size ");
337706cfae4SConrad Meyer totalDSize64 += fSize64;
338706cfae4SConrad Meyer srcPtr += fileSizes[fileNb];
339706cfae4SConrad Meyer }
340706cfae4SConrad Meyer { size_t const decodedSize = (size_t)totalDSize64;
341706cfae4SConrad Meyer assert((U64)decodedSize == totalDSize64); /* check overflow */
342706cfae4SConrad Meyer free(*resultBufferPtr);
343706cfae4SConrad Meyer *resultBufferPtr = malloc(decodedSize);
344706cfae4SConrad Meyer if (!(*resultBufferPtr)) {
345706cfae4SConrad Meyer RETURN_ERROR(33, BMK_benchOutcome_t, "not enough memory");
346706cfae4SConrad Meyer }
347706cfae4SConrad Meyer if (totalDSize64 > decodedSize) { /* size_t overflow */
348706cfae4SConrad Meyer free(*resultBufferPtr);
349706cfae4SConrad Meyer RETURN_ERROR(32, BMK_benchOutcome_t, "original size is too large");
350706cfae4SConrad Meyer }
351706cfae4SConrad Meyer cSize = srcSize;
352706cfae4SConrad Meyer srcSize = decodedSize;
353706cfae4SConrad Meyer ratio = (double)srcSize / (double)cSize;
354706cfae4SConrad Meyer }
355706cfae4SConrad Meyer }
356706cfae4SConrad Meyer
357706cfae4SConrad Meyer /* Init data blocks */
358706cfae4SConrad Meyer { const char* srcPtr = (const char*)srcBuffer;
359706cfae4SConrad Meyer char* cPtr = (char*)compressedBuffer;
360706cfae4SConrad Meyer char* resPtr = (char*)(*resultBufferPtr);
361706cfae4SConrad Meyer U32 fileNb;
362706cfae4SConrad Meyer for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) {
363706cfae4SConrad Meyer size_t remaining = fileSizes[fileNb];
364706cfae4SConrad Meyer U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly) ? 1 : (U32)((remaining + (blockSize-1)) / blockSize);
365706cfae4SConrad Meyer U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
366706cfae4SConrad Meyer for ( ; nbBlocks<blockEnd; nbBlocks++) {
367706cfae4SConrad Meyer size_t const thisBlockSize = MIN(remaining, blockSize);
368706cfae4SConrad Meyer srcPtrs[nbBlocks] = srcPtr;
369706cfae4SConrad Meyer srcSizes[nbBlocks] = thisBlockSize;
370706cfae4SConrad Meyer cPtrs[nbBlocks] = cPtr;
371706cfae4SConrad Meyer cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly) ? thisBlockSize : ZSTD_compressBound(thisBlockSize);
372706cfae4SConrad Meyer resPtrs[nbBlocks] = resPtr;
373706cfae4SConrad Meyer resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly) ? (size_t) ZSTD_findDecompressedSize(srcPtr, thisBlockSize) : thisBlockSize;
374706cfae4SConrad Meyer srcPtr += thisBlockSize;
375706cfae4SConrad Meyer cPtr += cCapacities[nbBlocks];
376706cfae4SConrad Meyer resPtr += thisBlockSize;
377706cfae4SConrad Meyer remaining -= thisBlockSize;
378af73257bSConrad Meyer if (adv->mode == BMK_decodeOnly) {
379af73257bSConrad Meyer cSizes[nbBlocks] = thisBlockSize;
380af73257bSConrad Meyer benchResult.cSize = thisBlockSize;
381b3392d84SAllan Jude } } } }
382706cfae4SConrad Meyer
3833f774a5eSConrad Meyer /* warming up `compressedBuffer` */
384706cfae4SConrad Meyer if (adv->mode == BMK_decodeOnly) {
385706cfae4SConrad Meyer memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
386706cfae4SConrad Meyer } else {
387706cfae4SConrad Meyer RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
388706cfae4SConrad Meyer }
389706cfae4SConrad Meyer
390706cfae4SConrad Meyer /* Bench */
391706cfae4SConrad Meyer { U64 const crcOrig = (adv->mode == BMK_decodeOnly) ? 0 : XXH64(srcBuffer, srcSize, 0);
392706cfae4SConrad Meyer # define NB_MARKS 4
393706cfae4SConrad Meyer const char* marks[NB_MARKS] = { " |", " /", " =", " \\" };
394706cfae4SConrad Meyer U32 markNb = 0;
395706cfae4SConrad Meyer int compressionCompleted = (adv->mode == BMK_decodeOnly);
396706cfae4SConrad Meyer int decompressionCompleted = (adv->mode == BMK_compressOnly);
397af73257bSConrad Meyer BMK_benchParams_t cbp, dbp;
398706cfae4SConrad Meyer BMK_initCCtxArgs cctxprep;
399706cfae4SConrad Meyer BMK_initDCtxArgs dctxprep;
400af73257bSConrad Meyer
401ea684039SConrad Meyer cbp.benchFn = local_defaultCompress; /* ZSTD_compress2 */
402af73257bSConrad Meyer cbp.benchPayload = cctx;
403ea684039SConrad Meyer cbp.initFn = local_initCCtx; /* BMK_initCCtx */
404af73257bSConrad Meyer cbp.initPayload = &cctxprep;
405af73257bSConrad Meyer cbp.errorFn = ZSTD_isError;
406af73257bSConrad Meyer cbp.blockCount = nbBlocks;
407af73257bSConrad Meyer cbp.srcBuffers = srcPtrs;
408af73257bSConrad Meyer cbp.srcSizes = srcSizes;
409af73257bSConrad Meyer cbp.dstBuffers = cPtrs;
410af73257bSConrad Meyer cbp.dstCapacities = cCapacities;
411af73257bSConrad Meyer cbp.blockResults = cSizes;
412af73257bSConrad Meyer
413706cfae4SConrad Meyer cctxprep.cctx = cctx;
414706cfae4SConrad Meyer cctxprep.dictBuffer = dictBuffer;
415706cfae4SConrad Meyer cctxprep.dictBufferSize = dictBufferSize;
416706cfae4SConrad Meyer cctxprep.cLevel = cLevel;
417706cfae4SConrad Meyer cctxprep.comprParams = comprParams;
418706cfae4SConrad Meyer cctxprep.adv = adv;
419af73257bSConrad Meyer
420af73257bSConrad Meyer dbp.benchFn = local_defaultDecompress;
421af73257bSConrad Meyer dbp.benchPayload = dctx;
422af73257bSConrad Meyer dbp.initFn = local_initDCtx;
423af73257bSConrad Meyer dbp.initPayload = &dctxprep;
424af73257bSConrad Meyer dbp.errorFn = ZSTD_isError;
425af73257bSConrad Meyer dbp.blockCount = nbBlocks;
426af73257bSConrad Meyer dbp.srcBuffers = (const void* const *) cPtrs;
427af73257bSConrad Meyer dbp.srcSizes = cSizes;
428af73257bSConrad Meyer dbp.dstBuffers = resPtrs;
429af73257bSConrad Meyer dbp.dstCapacities = resSizes;
430af73257bSConrad Meyer dbp.blockResults = NULL;
431af73257bSConrad Meyer
432706cfae4SConrad Meyer dctxprep.dctx = dctx;
433706cfae4SConrad Meyer dctxprep.dictBuffer = dictBuffer;
434706cfae4SConrad Meyer dctxprep.dictBufferSize = dictBufferSize;
435706cfae4SConrad Meyer
436b3392d84SAllan Jude OUTPUTLEVEL(2, "\r%70s\r", ""); /* blank line */
437b3392d84SAllan Jude assert(srcSize < UINT_MAX);
438b3392d84SAllan Jude OUTPUTLEVEL(2, "%2s-%-17.17s :%10u -> \r", marks[markNb], displayName, (unsigned)srcSize);
439706cfae4SConrad Meyer
440706cfae4SConrad Meyer while (!(compressionCompleted && decompressionCompleted)) {
441706cfae4SConrad Meyer if (!compressionCompleted) {
442af73257bSConrad Meyer BMK_runOutcome_t const cOutcome = BMK_benchTimedFn( timeStateCompress, cbp);
443706cfae4SConrad Meyer
444706cfae4SConrad Meyer if (!BMK_isSuccessful_runOutcome(cOutcome)) {
445706cfae4SConrad Meyer return BMK_benchOutcome_error();
446706cfae4SConrad Meyer }
447706cfae4SConrad Meyer
448706cfae4SConrad Meyer { BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome);
449706cfae4SConrad Meyer cSize = cResult.sumOfReturn;
450b3392d84SAllan Jude ratio = (double)srcSize / (double)cSize;
451706cfae4SConrad Meyer { BMK_benchResult_t newResult;
4523f774a5eSConrad Meyer newResult.cSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / cResult.nanoSecPerRun);
453706cfae4SConrad Meyer benchResult.cSize = cSize;
454706cfae4SConrad Meyer if (newResult.cSpeed > benchResult.cSpeed)
455706cfae4SConrad Meyer benchResult.cSpeed = newResult.cSpeed;
456a19eddc3SBaptiste Daroussin } }
457a19eddc3SBaptiste Daroussin
4581767cc49SConrad Meyer { int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
459b3392d84SAllan Jude assert(cSize < UINT_MAX);
460b3392d84SAllan Jude OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \r",
461706cfae4SConrad Meyer marks[markNb], displayName,
462af73257bSConrad Meyer (unsigned)srcSize, (unsigned)cSize,
4631767cc49SConrad Meyer ratioAccuracy, ratio,
464b3392d84SAllan Jude benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT);
4651767cc49SConrad Meyer }
466706cfae4SConrad Meyer compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress);
467706cfae4SConrad Meyer }
468706cfae4SConrad Meyer
469706cfae4SConrad Meyer if(!decompressionCompleted) {
470af73257bSConrad Meyer BMK_runOutcome_t const dOutcome = BMK_benchTimedFn(timeStateDecompress, dbp);
471706cfae4SConrad Meyer
472706cfae4SConrad Meyer if(!BMK_isSuccessful_runOutcome(dOutcome)) {
473706cfae4SConrad Meyer return BMK_benchOutcome_error();
474706cfae4SConrad Meyer }
475706cfae4SConrad Meyer
476706cfae4SConrad Meyer { BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);
4773f774a5eSConrad Meyer U64 const newDSpeed = (U64)((double)srcSize * TIMELOOP_NANOSEC / dResult.nanoSecPerRun);
478706cfae4SConrad Meyer if (newDSpeed > benchResult.dSpeed)
479706cfae4SConrad Meyer benchResult.dSpeed = newDSpeed;
480706cfae4SConrad Meyer }
481706cfae4SConrad Meyer
482706cfae4SConrad Meyer { int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
483b3392d84SAllan Jude OUTPUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r",
484706cfae4SConrad Meyer marks[markNb], displayName,
485bc64b5ceSConrad Meyer (unsigned)srcSize, (unsigned)cSize,
486706cfae4SConrad Meyer ratioAccuracy, ratio,
487b3392d84SAllan Jude benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT,
488706cfae4SConrad Meyer (double)benchResult.dSpeed / MB_UNIT);
489706cfae4SConrad Meyer }
490706cfae4SConrad Meyer decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress);
491706cfae4SConrad Meyer }
492af73257bSConrad Meyer markNb = (markNb+1) % NB_MARKS;
493706cfae4SConrad Meyer } /* while (!(compressionCompleted && decompressionCompleted)) */
494a19eddc3SBaptiste Daroussin
495a19eddc3SBaptiste Daroussin /* CRC Checking */
496706cfae4SConrad Meyer { const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);
497706cfae4SConrad Meyer U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
498706cfae4SConrad Meyer if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) {
499a19eddc3SBaptiste Daroussin size_t u;
500af73257bSConrad Meyer DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n",
501af73257bSConrad Meyer displayName, (unsigned)crcOrig, (unsigned)crcCheck);
502a19eddc3SBaptiste Daroussin for (u=0; u<srcSize; u++) {
503706cfae4SConrad Meyer if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) {
504af73257bSConrad Meyer unsigned segNb, bNb, pos;
505a19eddc3SBaptiste Daroussin size_t bacc = 0;
506af73257bSConrad Meyer DISPLAY("Decoding error at pos %u ", (unsigned)u);
507a19eddc3SBaptiste Daroussin for (segNb = 0; segNb < nbBlocks; segNb++) {
508706cfae4SConrad Meyer if (bacc + srcSizes[segNb] > u) break;
509706cfae4SConrad Meyer bacc += srcSizes[segNb];
510a19eddc3SBaptiste Daroussin }
511a19eddc3SBaptiste Daroussin pos = (U32)(u - bacc);
512a19eddc3SBaptiste Daroussin bNb = pos / (128 KB);
513affe9eafSBaptiste Daroussin DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos);
5143f774a5eSConrad Meyer { size_t const lowest = (u>5) ? 5 : u;
5153f774a5eSConrad Meyer size_t n;
5161767cc49SConrad Meyer DISPLAY("origin: ");
5173f774a5eSConrad Meyer for (n=lowest; n>0; n--)
5183f774a5eSConrad Meyer DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u-n]);
519a19eddc3SBaptiste Daroussin DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
5203f774a5eSConrad Meyer for (n=1; n<3; n++)
5213f774a5eSConrad Meyer DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]);
522a19eddc3SBaptiste Daroussin DISPLAY(" \n");
5231767cc49SConrad Meyer DISPLAY("decode: ");
524b3392d84SAllan Jude for (n=lowest; n>0; n--)
5253f774a5eSConrad Meyer DISPLAY("%02X ", resultBuffer[u-n]);
526706cfae4SConrad Meyer DISPLAY(" :%02X: ", resultBuffer[u]);
5273f774a5eSConrad Meyer for (n=1; n<3; n++)
5283f774a5eSConrad Meyer DISPLAY("%02X ", resultBuffer[u+n]);
529a19eddc3SBaptiste Daroussin DISPLAY(" \n");
530a19eddc3SBaptiste Daroussin }
531a19eddc3SBaptiste Daroussin break;
532a19eddc3SBaptiste Daroussin }
533a19eddc3SBaptiste Daroussin if (u==srcSize-1) { /* should never happen */
534a19eddc3SBaptiste Daroussin DISPLAY("no difference detected\n");
535706cfae4SConrad Meyer }
536ea684039SConrad Meyer } /* for (u=0; u<srcSize; u++) */
537ea684039SConrad Meyer } /* if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) */
538706cfae4SConrad Meyer } /* CRC Checking */
539a19eddc3SBaptiste Daroussin
540706cfae4SConrad Meyer if (displayLevel == 1) { /* hidden display mode -q, used by python speed benchmark */
541706cfae4SConrad Meyer double const cSpeed = (double)benchResult.cSpeed / MB_UNIT;
542706cfae4SConrad Meyer double const dSpeed = (double)benchResult.dSpeed / MB_UNIT;
543706cfae4SConrad Meyer if (adv->additionalParam) {
544b3392d84SAllan 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);
545706cfae4SConrad Meyer } else {
546b3392d84SAllan Jude OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName);
547a19eddc3SBaptiste Daroussin }
548706cfae4SConrad Meyer }
549706cfae4SConrad Meyer
550b3392d84SAllan Jude OUTPUTLEVEL(2, "%2i#\n", cLevel);
551a19eddc3SBaptiste Daroussin } /* Bench */
552a19eddc3SBaptiste Daroussin
553706cfae4SConrad Meyer benchResult.cMem = (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx);
554706cfae4SConrad Meyer return BMK_benchOutcome_setValidResult(benchResult);
555a19eddc3SBaptiste Daroussin }
556a19eddc3SBaptiste Daroussin
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)557706cfae4SConrad Meyer BMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,
558706cfae4SConrad Meyer void* dstBuffer, size_t dstCapacity,
559706cfae4SConrad Meyer const size_t* fileSizes, unsigned nbFiles,
560706cfae4SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams,
561706cfae4SConrad Meyer const void* dictBuffer, size_t dictBufferSize,
562706cfae4SConrad Meyer int displayLevel, const char* displayName, const BMK_advancedParams_t* adv)
563706cfae4SConrad Meyer
564706cfae4SConrad Meyer {
565706cfae4SConrad Meyer int const dstParamsError = !dstBuffer ^ !dstCapacity; /* must be both NULL or none */
566706cfae4SConrad Meyer
567706cfae4SConrad Meyer size_t const blockSize = ((adv->blockSize>=32 && (adv->mode != BMK_decodeOnly)) ? adv->blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
568706cfae4SConrad Meyer U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles;
569706cfae4SConrad Meyer
570706cfae4SConrad Meyer /* these are the blockTable parameters, just split up */
571706cfae4SConrad Meyer const void ** const srcPtrs = (const void**)malloc(maxNbBlocks * sizeof(void*));
572706cfae4SConrad Meyer size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
573706cfae4SConrad Meyer
574706cfae4SConrad Meyer
575706cfae4SConrad Meyer void ** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
576706cfae4SConrad Meyer size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
577706cfae4SConrad Meyer size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
578706cfae4SConrad Meyer
579706cfae4SConrad Meyer void ** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
580706cfae4SConrad Meyer size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
581706cfae4SConrad Meyer
582706cfae4SConrad Meyer BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
583706cfae4SConrad Meyer BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
584706cfae4SConrad Meyer
585706cfae4SConrad Meyer ZSTD_CCtx* const cctx = ZSTD_createCCtx();
586706cfae4SConrad Meyer ZSTD_DCtx* const dctx = ZSTD_createDCtx();
587706cfae4SConrad Meyer
588706cfae4SConrad Meyer const size_t maxCompressedSize = dstCapacity ? dstCapacity : ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);
589706cfae4SConrad Meyer
590706cfae4SConrad Meyer void* const internalDstBuffer = dstBuffer ? NULL : malloc(maxCompressedSize);
591706cfae4SConrad Meyer void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer;
592706cfae4SConrad Meyer
593706cfae4SConrad Meyer BMK_benchOutcome_t outcome = BMK_benchOutcome_error(); /* error by default */
594706cfae4SConrad Meyer
595706cfae4SConrad Meyer void* resultBuffer = srcSize ? malloc(srcSize) : NULL;
596706cfae4SConrad Meyer
597706cfae4SConrad Meyer int allocationincomplete = !srcPtrs || !srcSizes || !cPtrs ||
598706cfae4SConrad Meyer !cSizes || !cCapacities || !resPtrs || !resSizes ||
599706cfae4SConrad Meyer !timeStateCompress || !timeStateDecompress ||
600706cfae4SConrad Meyer !cctx || !dctx ||
601706cfae4SConrad Meyer !compressedBuffer || !resultBuffer;
602706cfae4SConrad Meyer
603706cfae4SConrad Meyer
604706cfae4SConrad Meyer if (!allocationincomplete && !dstParamsError) {
605706cfae4SConrad Meyer outcome = BMK_benchMemAdvancedNoAlloc(srcPtrs, srcSizes,
606706cfae4SConrad Meyer cPtrs, cCapacities, cSizes,
607706cfae4SConrad Meyer resPtrs, resSizes,
608706cfae4SConrad Meyer &resultBuffer,
609706cfae4SConrad Meyer compressedBuffer, maxCompressedSize,
610706cfae4SConrad Meyer timeStateCompress, timeStateDecompress,
611706cfae4SConrad Meyer srcBuffer, srcSize,
612706cfae4SConrad Meyer fileSizes, nbFiles,
613706cfae4SConrad Meyer cLevel, comprParams,
614706cfae4SConrad Meyer dictBuffer, dictBufferSize,
615706cfae4SConrad Meyer cctx, dctx,
616706cfae4SConrad Meyer displayLevel, displayName, adv);
617706cfae4SConrad Meyer }
618706cfae4SConrad Meyer
619706cfae4SConrad Meyer /* clean up */
620706cfae4SConrad Meyer BMK_freeTimedFnState(timeStateCompress);
621706cfae4SConrad Meyer BMK_freeTimedFnState(timeStateDecompress);
622706cfae4SConrad Meyer
623706cfae4SConrad Meyer ZSTD_freeCCtx(cctx);
624706cfae4SConrad Meyer ZSTD_freeDCtx(dctx);
625706cfae4SConrad Meyer
626706cfae4SConrad Meyer free(internalDstBuffer);
627706cfae4SConrad Meyer free(resultBuffer);
628706cfae4SConrad Meyer
629706cfae4SConrad Meyer free((void*)srcPtrs);
630706cfae4SConrad Meyer free(srcSizes);
631706cfae4SConrad Meyer free(cPtrs);
632706cfae4SConrad Meyer free(cSizes);
633706cfae4SConrad Meyer free(cCapacities);
634706cfae4SConrad Meyer free(resPtrs);
635706cfae4SConrad Meyer free(resSizes);
636706cfae4SConrad Meyer
637706cfae4SConrad Meyer if(allocationincomplete) {
638706cfae4SConrad Meyer RETURN_ERROR(31, BMK_benchOutcome_t, "allocation error : not enough memory");
639706cfae4SConrad Meyer }
640706cfae4SConrad Meyer
641706cfae4SConrad Meyer if(dstParamsError) {
642706cfae4SConrad Meyer RETURN_ERROR(32, BMK_benchOutcome_t, "Dst parameters not coherent");
643706cfae4SConrad Meyer }
644706cfae4SConrad Meyer return outcome;
645706cfae4SConrad Meyer }
646706cfae4SConrad 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)647706cfae4SConrad Meyer BMK_benchOutcome_t BMK_benchMem(const void* srcBuffer, size_t srcSize,
648706cfae4SConrad Meyer const size_t* fileSizes, unsigned nbFiles,
649706cfae4SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams,
650706cfae4SConrad Meyer const void* dictBuffer, size_t dictBufferSize,
651706cfae4SConrad Meyer int displayLevel, const char* displayName) {
652706cfae4SConrad Meyer
653706cfae4SConrad Meyer BMK_advancedParams_t const adv = BMK_initAdvancedParams();
654706cfae4SConrad Meyer return BMK_benchMemAdvanced(srcBuffer, srcSize,
655706cfae4SConrad Meyer NULL, 0,
656706cfae4SConrad Meyer fileSizes, nbFiles,
657706cfae4SConrad Meyer cLevel, comprParams,
658706cfae4SConrad Meyer dictBuffer, dictBufferSize,
659706cfae4SConrad Meyer displayLevel, displayName, &adv);
660706cfae4SConrad Meyer }
661706cfae4SConrad 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)662706cfae4SConrad Meyer static BMK_benchOutcome_t BMK_benchCLevel(const void* srcBuffer, size_t benchedSize,
663706cfae4SConrad Meyer const size_t* fileSizes, unsigned nbFiles,
664706cfae4SConrad Meyer int cLevel, const ZSTD_compressionParameters* comprParams,
665706cfae4SConrad Meyer const void* dictBuffer, size_t dictBufferSize,
666706cfae4SConrad Meyer int displayLevel, const char* displayName,
667706cfae4SConrad Meyer BMK_advancedParams_t const * const adv)
668706cfae4SConrad Meyer {
669706cfae4SConrad Meyer const char* pch = strrchr(displayName, '\\'); /* Windows */
670706cfae4SConrad Meyer if (!pch) pch = strrchr(displayName, '/'); /* Linux */
671706cfae4SConrad Meyer if (pch) displayName = pch+1;
672706cfae4SConrad Meyer
673706cfae4SConrad Meyer if (adv->realTime) {
674706cfae4SConrad Meyer DISPLAYLEVEL(2, "Note : switching to real-time priority \n");
675706cfae4SConrad Meyer SET_REALTIME_PRIORITY;
676706cfae4SConrad Meyer }
677706cfae4SConrad Meyer
678706cfae4SConrad Meyer if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */
679b3392d84SAllan Jude OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n",
680706cfae4SConrad Meyer ZSTD_VERSION_STRING, ZSTD_GIT_COMMIT_STRING,
681af73257bSConrad Meyer (unsigned)benchedSize, adv->nbSeconds, (unsigned)(adv->blockSize>>10));
682706cfae4SConrad Meyer
683706cfae4SConrad Meyer return BMK_benchMemAdvanced(srcBuffer, benchedSize,
684706cfae4SConrad Meyer NULL, 0,
685706cfae4SConrad Meyer fileSizes, nbFiles,
686706cfae4SConrad Meyer cLevel, comprParams,
687706cfae4SConrad Meyer dictBuffer, dictBufferSize,
688706cfae4SConrad Meyer displayLevel, displayName, adv);
689706cfae4SConrad Meyer }
690706cfae4SConrad Meyer
BMK_syntheticTest(int cLevel,double compressibility,const ZSTD_compressionParameters * compressionParams,int displayLevel,const BMK_advancedParams_t * adv)691706cfae4SConrad Meyer BMK_benchOutcome_t BMK_syntheticTest(int cLevel, double compressibility,
692706cfae4SConrad Meyer const ZSTD_compressionParameters* compressionParams,
693706cfae4SConrad Meyer int displayLevel, const BMK_advancedParams_t* adv)
694706cfae4SConrad Meyer {
695706cfae4SConrad Meyer char name[20] = {0};
696706cfae4SConrad Meyer size_t const benchedSize = 10000000;
697706cfae4SConrad Meyer void* srcBuffer;
698706cfae4SConrad Meyer BMK_benchOutcome_t res;
699706cfae4SConrad Meyer
700706cfae4SConrad Meyer if (cLevel > ZSTD_maxCLevel()) {
701706cfae4SConrad Meyer RETURN_ERROR(15, BMK_benchOutcome_t, "Invalid Compression Level");
702706cfae4SConrad Meyer }
703706cfae4SConrad Meyer
704706cfae4SConrad Meyer /* Memory allocation */
705706cfae4SConrad Meyer srcBuffer = malloc(benchedSize);
706706cfae4SConrad Meyer if (!srcBuffer) RETURN_ERROR(21, BMK_benchOutcome_t, "not enough memory");
707706cfae4SConrad Meyer
708706cfae4SConrad Meyer /* Fill input buffer */
709706cfae4SConrad Meyer RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);
710706cfae4SConrad Meyer
711706cfae4SConrad Meyer /* Bench */
712706cfae4SConrad Meyer snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100));
713706cfae4SConrad Meyer res = BMK_benchCLevel(srcBuffer, benchedSize,
714706cfae4SConrad Meyer &benchedSize /* ? */, 1 /* ? */,
715706cfae4SConrad Meyer cLevel, compressionParams,
716706cfae4SConrad Meyer NULL, 0, /* dictionary */
717706cfae4SConrad Meyer displayLevel, name, adv);
718706cfae4SConrad Meyer
719706cfae4SConrad Meyer /* clean up */
720706cfae4SConrad Meyer free(srcBuffer);
721706cfae4SConrad Meyer
722706cfae4SConrad Meyer return res;
723706cfae4SConrad Meyer }
724706cfae4SConrad Meyer
725706cfae4SConrad Meyer
726a19eddc3SBaptiste Daroussin
BMK_findMaxMem(U64 requiredMem)727a19eddc3SBaptiste Daroussin static size_t BMK_findMaxMem(U64 requiredMem)
728a19eddc3SBaptiste Daroussin {
729a19eddc3SBaptiste Daroussin size_t const step = 64 MB;
730a19eddc3SBaptiste Daroussin BYTE* testmem = NULL;
731a19eddc3SBaptiste Daroussin
732a19eddc3SBaptiste Daroussin requiredMem = (((requiredMem >> 26) + 1) << 26);
733a19eddc3SBaptiste Daroussin requiredMem += step;
734a19eddc3SBaptiste Daroussin if (requiredMem > maxMemory) requiredMem = maxMemory;
735a19eddc3SBaptiste Daroussin
736a19eddc3SBaptiste Daroussin do {
737a19eddc3SBaptiste Daroussin testmem = (BYTE*)malloc((size_t)requiredMem);
738a19eddc3SBaptiste Daroussin requiredMem -= step;
739706cfae4SConrad Meyer } while (!testmem && requiredMem > 0);
740a19eddc3SBaptiste Daroussin
741a19eddc3SBaptiste Daroussin free(testmem);
742a19eddc3SBaptiste Daroussin return (size_t)(requiredMem);
743a19eddc3SBaptiste Daroussin }
744a19eddc3SBaptiste Daroussin
745a19eddc3SBaptiste Daroussin /*! BMK_loadFiles() :
74642239e68SConrad Meyer * Loads `buffer` with content of files listed within `fileNamesTable`.
74742239e68SConrad Meyer * At most, fills `buffer` entirely. */
BMK_loadFiles(void * buffer,size_t bufferSize,size_t * fileSizes,const char * const * fileNamesTable,unsigned nbFiles,int displayLevel)748706cfae4SConrad Meyer static int BMK_loadFiles(void* buffer, size_t bufferSize,
749a19eddc3SBaptiste Daroussin size_t* fileSizes,
750706cfae4SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles,
751706cfae4SConrad Meyer int displayLevel)
752a19eddc3SBaptiste Daroussin {
753a19eddc3SBaptiste Daroussin size_t pos = 0, totalSize = 0;
754a19eddc3SBaptiste Daroussin unsigned n;
755a19eddc3SBaptiste Daroussin for (n=0; n<nbFiles; n++) {
756ea684039SConrad Meyer U64 fileSize = UTIL_getFileSize(fileNamesTable[n]); /* last file may be shortened */
757a19eddc3SBaptiste Daroussin if (UTIL_isDirectory(fileNamesTable[n])) {
758a19eddc3SBaptiste Daroussin DISPLAYLEVEL(2, "Ignoring %s directory... \n", fileNamesTable[n]);
759a19eddc3SBaptiste Daroussin fileSizes[n] = 0;
760a19eddc3SBaptiste Daroussin continue;
761a19eddc3SBaptiste Daroussin }
7621767cc49SConrad Meyer if (fileSize == UTIL_FILESIZE_UNKNOWN) {
7631767cc49SConrad Meyer DISPLAYLEVEL(2, "Cannot evaluate size of %s, ignoring ... \n", fileNamesTable[n]);
7641767cc49SConrad Meyer fileSizes[n] = 0;
7651767cc49SConrad Meyer continue;
7661767cc49SConrad Meyer }
767ea684039SConrad Meyer { FILE* const f = fopen(fileNamesTable[n], "rb");
768ea684039SConrad Meyer if (f==NULL) RETURN_ERROR_INT(10, "impossible to open file %s", fileNamesTable[n]);
769b3392d84SAllan Jude OUTPUTLEVEL(2, "Loading %s... \r", fileNamesTable[n]);
770a19eddc3SBaptiste Daroussin if (fileSize > bufferSize-pos) fileSize = bufferSize-pos, nbFiles=n; /* buffer too small - stop after this file */
771a19eddc3SBaptiste Daroussin { size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);
772ea684039SConrad Meyer if (readSize != (size_t)fileSize) RETURN_ERROR_INT(11, "could not read %s", fileNamesTable[n]);
773706cfae4SConrad Meyer pos += readSize;
774706cfae4SConrad Meyer }
775a19eddc3SBaptiste Daroussin fileSizes[n] = (size_t)fileSize;
776a19eddc3SBaptiste Daroussin totalSize += (size_t)fileSize;
777a19eddc3SBaptiste Daroussin fclose(f);
778ea684039SConrad Meyer } }
779a19eddc3SBaptiste Daroussin
780ea684039SConrad Meyer if (totalSize == 0) RETURN_ERROR_INT(12, "no data to bench");
781706cfae4SConrad Meyer return 0;
782a19eddc3SBaptiste Daroussin }
783a19eddc3SBaptiste Daroussin
BMK_benchFilesAdvanced(const char * const * fileNamesTable,unsigned nbFiles,const char * dictFileName,int cLevel,const ZSTD_compressionParameters * compressionParams,int displayLevel,const BMK_advancedParams_t * adv)784706cfae4SConrad Meyer BMK_benchOutcome_t BMK_benchFilesAdvanced(
785706cfae4SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles,
786706cfae4SConrad Meyer const char* dictFileName, int cLevel,
787706cfae4SConrad Meyer const ZSTD_compressionParameters* compressionParams,
788706cfae4SConrad Meyer int displayLevel, const BMK_advancedParams_t* adv)
789a19eddc3SBaptiste Daroussin {
790706cfae4SConrad Meyer void* srcBuffer = NULL;
791a19eddc3SBaptiste Daroussin size_t benchedSize;
792a19eddc3SBaptiste Daroussin void* dictBuffer = NULL;
793a19eddc3SBaptiste Daroussin size_t dictBufferSize = 0;
794706cfae4SConrad Meyer size_t* fileSizes = NULL;
795706cfae4SConrad Meyer BMK_benchOutcome_t res;
796a19eddc3SBaptiste Daroussin U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
797a19eddc3SBaptiste Daroussin
798706cfae4SConrad Meyer if (!nbFiles) {
799706cfae4SConrad Meyer RETURN_ERROR(14, BMK_benchOutcome_t, "No Files to Benchmark");
800706cfae4SConrad Meyer }
801706cfae4SConrad Meyer
802706cfae4SConrad Meyer if (cLevel > ZSTD_maxCLevel()) {
803706cfae4SConrad Meyer RETURN_ERROR(15, BMK_benchOutcome_t, "Invalid Compression Level");
804706cfae4SConrad Meyer }
805706cfae4SConrad Meyer
806b3392d84SAllan Jude if (totalSizeToLoad == UTIL_FILESIZE_UNKNOWN) {
807b3392d84SAllan Jude RETURN_ERROR(9, BMK_benchOutcome_t, "Error loading files");
808b3392d84SAllan Jude }
809b3392d84SAllan Jude
810706cfae4SConrad Meyer fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t));
811706cfae4SConrad Meyer if (!fileSizes) RETURN_ERROR(12, BMK_benchOutcome_t, "not enough memory for fileSizes");
812a19eddc3SBaptiste Daroussin
813a19eddc3SBaptiste Daroussin /* Load dictionary */
814a19eddc3SBaptiste Daroussin if (dictFileName != NULL) {
8151767cc49SConrad Meyer U64 const dictFileSize = UTIL_getFileSize(dictFileName);
816af73257bSConrad Meyer if (dictFileSize == UTIL_FILESIZE_UNKNOWN) {
817af73257bSConrad Meyer DISPLAYLEVEL(1, "error loading %s : %s \n", dictFileName, strerror(errno));
818af73257bSConrad Meyer free(fileSizes);
819af73257bSConrad Meyer RETURN_ERROR(9, BMK_benchOutcome_t, "benchmark aborted");
820af73257bSConrad Meyer }
821706cfae4SConrad Meyer if (dictFileSize > 64 MB) {
822706cfae4SConrad Meyer free(fileSizes);
823706cfae4SConrad Meyer RETURN_ERROR(10, BMK_benchOutcome_t, "dictionary file %s too large", dictFileName);
824706cfae4SConrad Meyer }
825a19eddc3SBaptiste Daroussin dictBufferSize = (size_t)dictFileSize;
826a19eddc3SBaptiste Daroussin dictBuffer = malloc(dictBufferSize);
827706cfae4SConrad Meyer if (dictBuffer==NULL) {
828706cfae4SConrad Meyer free(fileSizes);
829706cfae4SConrad Meyer RETURN_ERROR(11, BMK_benchOutcome_t, "not enough memory for dictionary (%u bytes)",
830af73257bSConrad Meyer (unsigned)dictBufferSize);
831706cfae4SConrad Meyer }
832706cfae4SConrad Meyer
833706cfae4SConrad Meyer { int const errorCode = BMK_loadFiles(dictBuffer, dictBufferSize,
834706cfae4SConrad Meyer fileSizes, &dictFileName /*?*/,
835706cfae4SConrad Meyer 1 /*?*/, displayLevel);
836706cfae4SConrad Meyer if (errorCode) {
837706cfae4SConrad Meyer res = BMK_benchOutcome_error();
838706cfae4SConrad Meyer goto _cleanUp;
839706cfae4SConrad Meyer } }
840a19eddc3SBaptiste Daroussin }
841a19eddc3SBaptiste Daroussin
842a19eddc3SBaptiste Daroussin /* Memory allocation & restrictions */
843a19eddc3SBaptiste Daroussin benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;
844a19eddc3SBaptiste Daroussin if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;
845a19eddc3SBaptiste Daroussin if (benchedSize < totalSizeToLoad)
846af73257bSConrad Meyer DISPLAY("Not enough memory; testing %u MB only...\n", (unsigned)(benchedSize >> 20));
847706cfae4SConrad Meyer
848706cfae4SConrad Meyer srcBuffer = benchedSize ? malloc(benchedSize) : NULL;
849706cfae4SConrad Meyer if (!srcBuffer) {
850706cfae4SConrad Meyer free(dictBuffer);
851706cfae4SConrad Meyer free(fileSizes);
852706cfae4SConrad Meyer RETURN_ERROR(12, BMK_benchOutcome_t, "not enough memory");
853706cfae4SConrad Meyer }
854a19eddc3SBaptiste Daroussin
855a19eddc3SBaptiste Daroussin /* Load input buffer */
856706cfae4SConrad Meyer { int const errorCode = BMK_loadFiles(srcBuffer, benchedSize,
857706cfae4SConrad Meyer fileSizes, fileNamesTable, nbFiles,
858706cfae4SConrad Meyer displayLevel);
859706cfae4SConrad Meyer if (errorCode) {
860706cfae4SConrad Meyer res = BMK_benchOutcome_error();
861706cfae4SConrad Meyer goto _cleanUp;
8621767cc49SConrad Meyer } }
863a19eddc3SBaptiste Daroussin
864706cfae4SConrad Meyer /* Bench */
865706cfae4SConrad Meyer { char mfName[20] = {0};
866706cfae4SConrad Meyer snprintf (mfName, sizeof(mfName), " %u files", nbFiles);
867706cfae4SConrad Meyer { const char* const displayName = (nbFiles > 1) ? mfName : fileNamesTable[0];
868706cfae4SConrad Meyer res = BMK_benchCLevel(srcBuffer, benchedSize,
869706cfae4SConrad Meyer fileSizes, nbFiles,
870706cfae4SConrad Meyer cLevel, compressionParams,
871706cfae4SConrad Meyer dictBuffer, dictBufferSize,
872706cfae4SConrad Meyer displayLevel, displayName,
873706cfae4SConrad Meyer adv);
874706cfae4SConrad Meyer } }
875706cfae4SConrad Meyer
876706cfae4SConrad Meyer _cleanUp:
877a19eddc3SBaptiste Daroussin free(srcBuffer);
878a19eddc3SBaptiste Daroussin free(dictBuffer);
879a19eddc3SBaptiste Daroussin free(fileSizes);
880706cfae4SConrad Meyer return res;
881a19eddc3SBaptiste Daroussin }
882a19eddc3SBaptiste Daroussin
883a19eddc3SBaptiste Daroussin
BMK_benchFiles(const char * const * fileNamesTable,unsigned nbFiles,const char * dictFileName,int cLevel,const ZSTD_compressionParameters * compressionParams,int displayLevel)884706cfae4SConrad Meyer BMK_benchOutcome_t BMK_benchFiles(
885706cfae4SConrad Meyer const char* const * fileNamesTable, unsigned nbFiles,
8861767cc49SConrad Meyer const char* dictFileName,
887706cfae4SConrad Meyer int cLevel, const ZSTD_compressionParameters* compressionParams,
888706cfae4SConrad Meyer int displayLevel)
889a19eddc3SBaptiste Daroussin {
890706cfae4SConrad Meyer BMK_advancedParams_t const adv = BMK_initAdvancedParams();
891706cfae4SConrad Meyer return BMK_benchFilesAdvanced(fileNamesTable, nbFiles, dictFileName, cLevel, compressionParams, displayLevel, &adv);
892a19eddc3SBaptiste Daroussin }
893