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