blob: 29ee595c174142bf519e6ef72d0ca50775c761df [file] [log] [blame]
Yann Collet32fb4072017-08-18 16:52:05 -07001/*
W. Felix Handte5d693cc2022-12-20 12:49:47 -05002 * Copyright (c) Meta Platforms, Inc. and affiliates.
Yann Collet4ded9e52016-08-30 10:04:33 -07003 * All rights reserved.
4 *
Yann Collet32fb4072017-08-18 16:52:05 -07005 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
Yann Collet3128e032017-09-08 00:09:23 -07008 * You may select, at your option, one of the above-listed licenses.
Yann Collet4ded9e52016-08-30 10:04:33 -07009 */
Yann Collet4856a002015-01-24 01:58:16 +010010
Przemyslaw Skibinski2f6ccee2016-12-21 13:23:34 +010011/* **************************************
Yann Collet7a225c02024-02-20 15:47:09 -080012 * Tuning parameters
13 ****************************************/
14#ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */
15# define BMK_TIMETEST_DEFAULT_S 3
Yann Collet500014a2017-01-19 16:59:56 -080016#endif
17
Yann Colletf3eca252015-10-22 15:31:46 +010018/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -080019 * Includes
20 ***************************************/
Yann Collet7170f512024-02-20 23:36:04 -080021/* this must be included first */
22#include "platform.h" /* Large Files support, compiler specifics */
23
24/* then following system includes */
Yann Collet7a225c02024-02-20 15:47:09 -080025#include <assert.h> /* assert */
Yann Colleted2fb6b2018-12-20 17:20:07 -080026#include <errno.h>
Yann Collet7a225c02024-02-20 15:47:09 -080027#include <stdio.h> /* fprintf, fopen */
28#include <stdlib.h> /* malloc, free */
29#include <string.h> /* memset, strerror */
Yann Collet7a225c02024-02-20 15:47:09 -080030#include "util.h" /* UTIL_getFileSize, UTIL_sleep */
W. Felix Handte7dcca6b2020-05-01 16:20:40 -040031#include "../lib/common/mem.h"
Yann Collet7a225c02024-02-20 15:47:09 -080032#include "benchfn.h"
33#include "timefn.h" /* UTIL_time_t */
W. Felix Handte4bd96a62022-01-06 00:20:49 -050034#ifndef ZSTD_STATIC_LINKING_ONLY
Yann Collet7a225c02024-02-20 15:47:09 -080035# define ZSTD_STATIC_LINKING_ONLY
W. Felix Handte4bd96a62022-01-06 00:20:49 -050036#endif
W. Felix Handte7dcca6b2020-05-01 16:20:40 -040037#include "../lib/zstd.h"
Yann Collet7a225c02024-02-20 15:47:09 -080038#include "datagen.h" /* RDG_genBuffer */
39#include "lorem.h" /* LOREM_genBuffer */
W. Felix Handte4bd96a62022-01-06 00:20:49 -050040#ifndef XXH_INLINE_ALL
Yann Collet7a225c02024-02-20 15:47:09 -080041# define XXH_INLINE_ALL
W. Felix Handte4bd96a62022-01-06 00:20:49 -050042#endif
W. Felix Handte7dcca6b2020-05-01 16:20:40 -040043#include "../lib/common/xxhash.h"
Nick Terrell09149be2021-04-30 15:02:12 -070044#include "../lib/zstd_errors.h"
Yann Collet7a225c02024-02-20 15:47:09 -080045#include "benchzstd.h"
Yann Collet4856a002015-01-24 01:58:16 +010046
Yann Colletf3eca252015-10-22 15:31:46 +010047/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -080048 * Constants
49 ***************************************/
inikepf2f59d72016-06-22 15:42:26 +020050#ifndef ZSTD_GIT_COMMIT
Yann Collet7a225c02024-02-20 15:47:09 -080051# define ZSTD_GIT_COMMIT_STRING ""
inikepd7d251c2016-06-22 16:13:25 +020052#else
Yann Collet7a225c02024-02-20 15:47:09 -080053# define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)
inikepf2f59d72016-06-22 15:42:26 +020054#endif
55
Yann Collet7a225c02024-02-20 15:47:09 -080056#define TIMELOOP_MICROSEC (1 * 1000000ULL) /* 1 second */
57#define TIMELOOP_NANOSEC (1 * 1000000000ULL) /* 1 second */
58#define ACTIVEPERIOD_MICROSEC (70 * TIMELOOP_MICROSEC) /* 70 seconds */
59#define COOLPERIOD_SEC 10
Yann Collet4856a002015-01-24 01:58:16 +010060
Yann Collet7a225c02024-02-20 15:47:09 -080061#define KB *(1 << 10)
62#define MB *(1 << 20)
63#define GB *(1U << 30)
Yann Collet4856a002015-01-24 01:58:16 +010064
Yann Collet55affc02018-08-28 11:21:09 -070065#define BMK_RUNTEST_DEFAULT_MS 1000
66
Yann Collet7a225c02024-02-20 15:47:09 -080067static const size_t maxMemory = (sizeof(size_t) == 4)
68 ?
69 /* 32-bit */ (2 GB - 64 MB)
70 :
71 /* 64-bit */ (size_t)(1ULL << ((sizeof(size_t) * 8) - 31));
Yann Collet4856a002015-01-24 01:58:16 +010072
Yann Colletf3eca252015-10-22 15:31:46 +010073/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -080074 * console display
75 ***************************************/
76#define DISPLAY(...) \
77 { \
78 fprintf(stderr, __VA_ARGS__); \
79 fflush(NULL); \
80 }
81#define DISPLAYLEVEL(l, ...) \
82 if (displayLevel >= l) { \
83 DISPLAY(__VA_ARGS__); \
84 }
85/* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : +
86 * progression; 4 : + information */
87#define OUTPUT(...) \
88 { \
89 fprintf(stdout, __VA_ARGS__); \
90 fflush(NULL); \
91 }
92#define OUTPUTLEVEL(l, ...) \
93 if (displayLevel >= l) { \
94 OUTPUT(__VA_ARGS__); \
95 }
Yann Colleted699e62015-12-16 02:37:24 +010096
97/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -080098 * Exceptions
99 ***************************************/
Yann Colleted699e62015-12-16 02:37:24 +0100100#ifndef DEBUG
Yann Collet7a225c02024-02-20 15:47:09 -0800101# define DEBUG 0
Yann Colleted699e62015-12-16 02:37:24 +0100102#endif
Yann Collet7a225c02024-02-20 15:47:09 -0800103#define DEBUGOUTPUT(...) \
104 { \
105 if (DEBUG) \
106 DISPLAY(__VA_ARGS__); \
107 }
George Lu20f4f322018-06-12 15:54:43 -0400108
Yann Collet7a225c02024-02-20 15:47:09 -0800109#define RETURN_ERROR_INT(errorNum, ...) \
110 { \
111 DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
112 DISPLAYLEVEL(1, "Error %i : ", errorNum); \
113 DISPLAYLEVEL(1, __VA_ARGS__); \
114 DISPLAYLEVEL(1, " \n"); \
115 return errorNum; \
116 }
Yann Collet4856a002015-01-24 01:58:16 +0100117
Yann Collet7a225c02024-02-20 15:47:09 -0800118#define CHECK_Z(zf) \
119 { \
120 size_t const zerr = zf; \
121 if (ZSTD_isError(zerr)) { \
122 DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
123 DISPLAY("Error : "); \
124 DISPLAY("%s failed : %s", #zf, ZSTD_getErrorName(zerr)); \
125 DISPLAY(" \n"); \
126 exit(1); \
127 } \
128 }
Yann Colletd613fd92018-12-06 19:27:37 -0800129
Yann Collet7a225c02024-02-20 15:47:09 -0800130#define RETURN_ERROR(errorNum, retType, ...) \
131 { \
132 retType r; \
133 memset(&r, 0, sizeof(retType)); \
134 DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \
135 DISPLAYLEVEL(1, "Error %i : ", errorNum); \
136 DISPLAYLEVEL(1, __VA_ARGS__); \
137 DISPLAYLEVEL(1, " \n"); \
138 r.tag = errorNum; \
139 return r; \
140 }
George Lu0d1ee222018-06-15 16:21:08 -0400141
Yann Collet588dfbc2024-02-20 19:21:01 -0800142/* replacement for snprintf(), which is not supported by C89
143 * sprintf() would be the supported one, but it's labelled unsafe,
144 * so some modern static analyzer will flag it as such, making it unusable.
145 * formatString_u() replaces snprintf() for the specific case where there are only %u arguments */
Yann Collete62e15d2024-02-20 22:43:22 -0800146static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value)
Yann Collet588dfbc2024-02-20 19:21:01 -0800147{
148 size_t written = 0;
149 int i;
150 assert(value <= 100);
151
152 for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; ++i) {
153 if (formatString[i] != '%') {
154 buffer[written++] = formatString[i];
155 continue;
156 }
157
158 if (formatString[++i] == 'u') {
159 /* Handle single digit */
160 if (value < 10) {
Yann Collete62e15d2024-02-20 22:43:22 -0800161 buffer[written++] = '0' + (char)value;
Yann Collet588dfbc2024-02-20 19:21:01 -0800162 } else if (value < 100) {
163 /* Handle two digits */
164 if (written >= buffer_size - 2) {
165 return -1; /* buffer overflow */
166 }
Yann Collete62e15d2024-02-20 22:43:22 -0800167 buffer[written++] = '0' + (char)(value / 10);
168 buffer[written++] = '0' + (char)(value % 10);
Yann Collet588dfbc2024-02-20 19:21:01 -0800169 } else { /* 100 */
170 if (written >= buffer_size - 3) {
171 return -1; /* buffer overflow */
172 }
173 buffer[written++] = '1';
174 buffer[written++] = '0';
175 buffer[written++] = '0';
176 }
177 } else if (formatString[i] == '%') { /* Check for escaped percent sign */
178 buffer[written++] = '%';
179 } else {
180 return -1; /* unsupported format */
181 }
182 }
183
184 if (written < buffer_size) {
185 buffer[written] = '\0';
186 } else {
187 buffer[0] = '\0'; /* Handle truncation */
188 }
189
Yann Collete62e15d2024-02-20 22:43:22 -0800190 return (int)written;
Yann Collet588dfbc2024-02-20 19:21:01 -0800191}
192
Yann Colletf3eca252015-10-22 15:31:46 +0100193/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -0800194 * Benchmark Parameters
195 ***************************************/
Stella Laua1f04d52017-09-01 14:52:51 -0700196
Yann Collet7a225c02024-02-20 15:47:09 -0800197BMK_advancedParams_t BMK_initAdvancedParams(void)
198{
Yann Collet2e45bad2018-08-23 14:21:18 -0700199 BMK_advancedParams_t const res = {
Yann Collet7a225c02024-02-20 15:47:09 -0800200 BMK_both, /* mode */
George Lu20f4f322018-06-12 15:54:43 -0400201 BMK_TIMETEST_DEFAULT_S, /* nbSeconds */
Yann Collet7a225c02024-02-20 15:47:09 -0800202 0, /* blockSize */
Yann Collet68a232c2024-02-23 13:13:03 -0800203 0, /* targetCBlockSize */
Yann Collet7a225c02024-02-20 15:47:09 -0800204 0, /* nbWorkers */
205 0, /* realTime */
206 0, /* additionalParam */
207 0, /* ldmFlag */
208 0, /* ldmMinMatch */
209 0, /* ldmHashLog */
210 0, /* ldmBuckSizeLog */
211 0, /* ldmHashRateLog */
212 ZSTD_ps_auto, /* literalCompressionMode */
213 0 /* useRowMatchFinder */
George Lu20f4f322018-06-12 15:54:43 -0400214 };
215 return res;
Stella Lau67d4a612017-09-02 21:10:36 -0700216}
217
Yann Colletf3eca252015-10-22 15:31:46 +0100218/* ********************************************************
Yann Collet7a225c02024-02-20 15:47:09 -0800219 * Bench functions
220 **********************************************************/
Yann Colletd9465012016-12-06 16:49:23 -0800221typedef struct {
222 const void* srcPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100223 size_t srcSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800224 void* cPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100225 size_t cRoom;
226 size_t cSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800227 void* resPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100228 size_t resSize;
229} blockParam_t;
230
Sean Purcell42bac7f2017-04-13 15:35:05 -0700231#undef MIN
232#undef MAX
Yann Collet7a225c02024-02-20 15:47:09 -0800233#define MIN(a, b) ((a) < (b) ? (a) : (b))
234#define MAX(a, b) ((a) > (b) ? (a) : (b))
Yann Collet1c00dc32015-10-21 08:22:25 +0100235
Yann Collet7a225c02024-02-20 15:47:09 -0800236static void BMK_initCCtx(
237 ZSTD_CCtx* ctx,
238 const void* dictBuffer,
239 size_t dictBufferSize,
240 int cLevel,
241 const ZSTD_compressionParameters* comprParams,
242 const BMK_advancedParams_t* adv)
Yann Colletb8701102019-01-25 15:11:50 -0800243{
Yann Collet5c686392018-11-15 16:12:39 -0800244 ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);
Yann Collet7a225c02024-02-20 15:47:09 -0800245 if (adv->nbWorkers == 1) {
Yann Colletd613fd92018-12-06 19:27:37 -0800246 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));
George Lu20f4f322018-06-12 15:54:43 -0400247 } else {
Yann Colletd613fd92018-12-06 19:27:37 -0800248 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers));
George Lu20f4f322018-06-12 15:54:43 -0400249 }
Yann Colletd613fd92018-12-06 19:27:37 -0800250 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel));
Yann Collet7a225c02024-02-20 15:47:09 -0800251 CHECK_Z(ZSTD_CCtx_setParameter(
252 ctx, ZSTD_c_useRowMatchFinder, adv->useRowMatchFinder));
253 CHECK_Z(ZSTD_CCtx_setParameter(
254 ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag));
Yann Colletd613fd92018-12-06 19:27:37 -0800255 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch));
256 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));
Yann Collet7a225c02024-02-20 15:47:09 -0800257 CHECK_Z(ZSTD_CCtx_setParameter(
258 ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));
259 CHECK_Z(ZSTD_CCtx_setParameter(
260 ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));
261 CHECK_Z(ZSTD_CCtx_setParameter(
262 ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));
263 CHECK_Z(ZSTD_CCtx_setParameter(
264 ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));
265 CHECK_Z(ZSTD_CCtx_setParameter(
266 ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));
267 CHECK_Z(ZSTD_CCtx_setParameter(
268 ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));
269 CHECK_Z(ZSTD_CCtx_setParameter(
270 ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));
271 CHECK_Z(ZSTD_CCtx_setParameter(
272 ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));
273 CHECK_Z(ZSTD_CCtx_setParameter(
274 ctx,
275 ZSTD_c_literalCompressionMode,
276 (int)adv->literalCompressionMode));
277 CHECK_Z(ZSTD_CCtx_setParameter(
278 ctx, ZSTD_c_strategy, (int)comprParams->strategy));
Yann Collet68a232c2024-02-23 13:13:03 -0800279 CHECK_Z(ZSTD_CCtx_setParameter(
280 ctx, ZSTD_c_targetCBlockSize, (int)adv->targetCBlockSize));
Yann Colletd613fd92018-12-06 19:27:37 -0800281 CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));
George Lu20f4f322018-06-12 15:54:43 -0400282}
283
Yann Collet7a225c02024-02-20 15:47:09 -0800284static void
285BMK_initDCtx(ZSTD_DCtx* dctx, const void* dictBuffer, size_t dictBufferSize)
286{
Yann Colletd613fd92018-12-06 19:27:37 -0800287 CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));
288 CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize));
George Lu20f4f322018-06-12 15:54:43 -0400289}
290
291typedef struct {
Yann Collet2e45bad2018-08-23 14:21:18 -0700292 ZSTD_CCtx* cctx;
George Lu20f4f322018-06-12 15:54:43 -0400293 const void* dictBuffer;
294 size_t dictBufferSize;
295 int cLevel;
296 const ZSTD_compressionParameters* comprParams;
297 const BMK_advancedParams_t* adv;
298} BMK_initCCtxArgs;
299
Yann Collet7a225c02024-02-20 15:47:09 -0800300static size_t local_initCCtx(void* payload)
301{
George Lu20f4f322018-06-12 15:54:43 -0400302 BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload;
Yann Collet7a225c02024-02-20 15:47:09 -0800303 BMK_initCCtx(
304 ag->cctx,
305 ag->dictBuffer,
306 ag->dictBufferSize,
307 ag->cLevel,
308 ag->comprParams,
309 ag->adv);
George Lu20f4f322018-06-12 15:54:43 -0400310 return 0;
311}
312
313typedef struct {
314 ZSTD_DCtx* dctx;
315 const void* dictBuffer;
316 size_t dictBufferSize;
317} BMK_initDCtxArgs;
318
Yann Collet7a225c02024-02-20 15:47:09 -0800319static size_t local_initDCtx(void* payload)
320{
George Lu20f4f322018-06-12 15:54:43 -0400321 BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload;
322 BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize);
323 return 0;
324}
325
Yann Collet2e45bad2018-08-23 14:21:18 -0700326/* `addArgs` is the context */
George Lu20f4f322018-06-12 15:54:43 -0400327static size_t local_defaultCompress(
Yann Collet7a225c02024-02-20 15:47:09 -0800328 const void* srcBuffer,
329 size_t srcSize,
330 void* dstBuffer,
331 size_t dstSize,
332 void* addArgs)
Yann Collet2e45bad2018-08-23 14:21:18 -0700333{
Yann Collet2e45bad2018-08-23 14:21:18 -0700334 ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs;
Yann Colletd8e215c2018-11-30 11:16:26 -0800335 return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize);
George Lu20f4f322018-06-12 15:54:43 -0400336}
337
Yann Collet2e45bad2018-08-23 14:21:18 -0700338/* `addArgs` is the context */
George Lu20f4f322018-06-12 15:54:43 -0400339static size_t local_defaultDecompress(
Yann Collet7a225c02024-02-20 15:47:09 -0800340 const void* srcBuffer,
341 size_t srcSize,
342 void* dstBuffer,
343 size_t dstCapacity,
344 void* addArgs)
Yann Collet2e45bad2018-08-23 14:21:18 -0700345{
Yann Collet7a225c02024-02-20 15:47:09 -0800346 size_t moreToFlush = 1;
Yann Collet2e45bad2018-08-23 14:21:18 -0700347 ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs;
George Lu20f4f322018-06-12 15:54:43 -0400348 ZSTD_inBuffer in;
349 ZSTD_outBuffer out;
Yann Collet7a225c02024-02-20 15:47:09 -0800350 in.src = srcBuffer;
351 in.size = srcSize;
352 in.pos = 0;
353 out.dst = dstBuffer;
354 out.size = dstCapacity;
355 out.pos = 0;
George Lu20f4f322018-06-12 15:54:43 -0400356 while (moreToFlush) {
Yann Collet7a225c02024-02-20 15:47:09 -0800357 if (out.pos == out.size) {
George Lud6121ad2018-06-22 17:25:16 -0700358 return (size_t)-ZSTD_error_dstSize_tooSmall;
359 }
Yann Collet34e146f2018-12-04 10:28:36 -0800360 moreToFlush = ZSTD_decompressStream(dctx, &out, &in);
George Lu20f4f322018-06-12 15:54:43 -0400361 if (ZSTD_isError(moreToFlush)) {
362 return moreToFlush;
363 }
364 }
365 return out.pos;
George Lu20f4f322018-06-12 15:54:43 -0400366}
367
Yann Collet2e45bad2018-08-23 14:21:18 -0700368/* ================================================================= */
369/* Benchmark Zstandard, mem-to-mem scenarios */
370/* ================================================================= */
371
372int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome)
373{
374 return outcome.tag == 0;
375}
376
377BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome)
378{
379 assert(outcome.tag == 0);
380 return outcome.internal_never_use_directly;
381}
382
Yann Collet6ce7b082018-08-24 15:59:57 -0700383static BMK_benchOutcome_t BMK_benchOutcome_error(void)
Yann Collet2e45bad2018-08-23 14:21:18 -0700384{
385 BMK_benchOutcome_t b;
386 memset(&b, 0, sizeof(b));
387 b.tag = 1;
388 return b;
389}
390
Yann Collet7a225c02024-02-20 15:47:09 -0800391static BMK_benchOutcome_t BMK_benchOutcome_setValidResult(
392 BMK_benchResult_t result)
Yann Collet2e45bad2018-08-23 14:21:18 -0700393{
394 BMK_benchOutcome_t b;
Yann Collet7a225c02024-02-20 15:47:09 -0800395 b.tag = 0;
Yann Collet2e45bad2018-08-23 14:21:18 -0700396 b.internal_never_use_directly = result;
397 return b;
398}
399
Yann Collet2e45bad2018-08-23 14:21:18 -0700400/* benchMem with no allocation */
Yann Collet7a225c02024-02-20 15:47:09 -0800401static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
402 const void** srcPtrs,
403 size_t* srcSizes,
404 void** cPtrs,
405 size_t* cCapacities,
406 size_t* cSizes,
407 void** resPtrs,
408 size_t* resSizes,
409 void** resultBufferPtr,
410 void* compressedBuffer,
411 size_t maxCompressedSize,
412 BMK_timedFnState_t* timeStateCompress,
413 BMK_timedFnState_t* timeStateDecompress,
Yann Collet2e45bad2018-08-23 14:21:18 -0700414
Yann Collet7a225c02024-02-20 15:47:09 -0800415 const void* srcBuffer,
416 size_t srcSize,
417 const size_t* fileSizes,
418 unsigned nbFiles,
419 const int cLevel,
420 const ZSTD_compressionParameters* comprParams,
421 const void* dictBuffer,
422 size_t dictBufferSize,
423 ZSTD_CCtx* cctx,
424 ZSTD_DCtx* dctx,
425 int displayLevel,
426 const char* displayName,
427 const BMK_advancedParams_t* adv)
Yann Collet1c00dc32015-10-21 08:22:25 +0100428{
Yann Collet7a225c02024-02-20 15:47:09 -0800429 size_t const blockSize =
430 ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
431 ? adv->blockSize
432 : srcSize)
433 + (!srcSize); /* avoid div by 0 */
Yann Collet2e45bad2018-08-23 14:21:18 -0700434 BMK_benchResult_t benchResult;
Yann Collete63c6312016-12-06 17:46:49 -0800435 size_t const loadedCompressedSize = srcSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800436 size_t cSize = 0;
437 double ratio = 0.;
Yann Colletde406ee2016-03-20 15:46:10 +0100438 U32 nbBlocks;
439
Yann Collet7a225c02024-02-20 15:47:09 -0800440 assert(cctx != NULL);
441 assert(dctx != NULL);
George Lu01d940b2018-06-11 10:59:05 -0400442
Yann Colletc776c462015-10-29 19:10:54 +0100443 /* init */
Yann Collet4da5bdf2018-08-23 18:04:50 -0700444 memset(&benchResult, 0, sizeof(benchResult));
Yann Collet7a225c02024-02-20 15:47:09 -0800445 if (strlen(displayName) > 17)
446 displayName +=
447 strlen(displayName) - 17; /* display last 17 characters */
Yann Collet58e70672023-02-07 08:47:39 -0800448 if (adv->mode == BMK_decodeOnly) {
449 /* benchmark only decompression : source must be already compressed */
Yann Colletc2007382017-04-04 15:35:06 -0700450 const char* srcPtr = (const char*)srcBuffer;
Yann Collet7a225c02024-02-20 15:47:09 -0800451 U64 totalDSize64 = 0;
Yann Collete63c6312016-12-06 17:46:49 -0800452 U32 fileNb;
Yann Collet7a225c02024-02-20 15:47:09 -0800453 for (fileNb = 0; fileNb < nbFiles; fileNb++) {
454 U64 const fSize64 =
455 ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]);
Yann Collet58e70672023-02-07 08:47:39 -0800456 if (fSize64 == ZSTD_CONTENTSIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -0800457 RETURN_ERROR(
458 32,
459 BMK_benchOutcome_t,
460 "Decompressed size cannot be determined: cannot benchmark");
Yann Collet58e70672023-02-07 08:47:39 -0800461 }
462 if (fSize64 == ZSTD_CONTENTSIZE_ERROR) {
Yann Collet7a225c02024-02-20 15:47:09 -0800463 RETURN_ERROR(
464 32,
465 BMK_benchOutcome_t,
466 "Error while trying to assess decompressed size: data may be invalid");
Yann Collet58e70672023-02-07 08:47:39 -0800467 }
Yann Colletc2007382017-04-04 15:35:06 -0700468 totalDSize64 += fSize64;
Yann Collete63c6312016-12-06 17:46:49 -0800469 srcPtr += fileSizes[fileNb];
470 }
Yann Collet7a225c02024-02-20 15:47:09 -0800471 {
472 size_t const decodedSize = (size_t)totalDSize64;
473 assert((U64)decodedSize == totalDSize64); /* check overflow */
George Lu5f490342018-06-18 11:59:45 -0700474 free(*resultBufferPtr);
Yann Collet7a225c02024-02-20 15:47:09 -0800475 if (totalDSize64 > decodedSize) { /* size_t overflow */
476 RETURN_ERROR(
477 32,
478 BMK_benchOutcome_t,
479 "decompressed size is too large for local system");
Yann Collet58e70672023-02-07 08:47:39 -0800480 }
George Lu5f490342018-06-18 11:59:45 -0700481 *resultBufferPtr = malloc(decodedSize);
482 if (!(*resultBufferPtr)) {
Yann Collet7a225c02024-02-20 15:47:09 -0800483 RETURN_ERROR(
484 33,
485 BMK_benchOutcome_t,
486 "allocation error: not enough memory");
George Lua8eea992018-06-19 10:58:22 -0700487 }
Yann Collet7a225c02024-02-20 15:47:09 -0800488 cSize = srcSize;
Yann Collete63c6312016-12-06 17:46:49 -0800489 srcSize = decodedSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800490 ratio = (double)srcSize / (double)cSize;
Yann Collet77e805e2018-08-21 18:19:27 -0700491 }
George Lu20f4f322018-06-12 15:54:43 -0400492 }
Yann Collete63c6312016-12-06 17:46:49 -0800493
George Lu20f4f322018-06-12 15:54:43 -0400494 /* Init data blocks */
Yann Collet7a225c02024-02-20 15:47:09 -0800495 {
496 const char* srcPtr = (const char*)srcBuffer;
497 char* cPtr = (char*)compressedBuffer;
498 char* resPtr = (char*)(*resultBufferPtr);
Yann Collet699b14d2016-03-17 19:37:33 +0100499 U32 fileNb;
Yann Collet7a225c02024-02-20 15:47:09 -0800500 for (nbBlocks = 0, fileNb = 0; fileNb < nbFiles; fileNb++) {
501 size_t remaining = fileSizes[fileNb];
502 U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly)
503 ? 1
504 : (U32)((remaining + (blockSize - 1)) / blockSize);
505 U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
506 for (; nbBlocks < blockEnd; nbBlocks++) {
Yann Colletde406ee2016-03-20 15:46:10 +0100507 size_t const thisBlockSize = MIN(remaining, blockSize);
Yann Collet7a225c02024-02-20 15:47:09 -0800508 srcPtrs[nbBlocks] = srcPtr;
509 srcSizes[nbBlocks] = thisBlockSize;
510 cPtrs[nbBlocks] = cPtr;
511 cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly)
512 ? thisBlockSize
513 : ZSTD_compressBound(thisBlockSize);
514 resPtrs[nbBlocks] = resPtr;
515 resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly)
516 ? (size_t)ZSTD_findDecompressedSize(
517 srcPtr, thisBlockSize)
518 : thisBlockSize;
Yann Colleted699e62015-12-16 02:37:24 +0100519 srcPtr += thisBlockSize;
George Lue148db32018-07-20 14:35:09 -0700520 cPtr += cCapacities[nbBlocks];
Yann Colleted699e62015-12-16 02:37:24 +0100521 resPtr += thisBlockSize;
522 remaining -= thisBlockSize;
Yann Collet3ba0d6d2018-11-13 14:15:12 -0800523 if (adv->mode == BMK_decodeOnly) {
Yann Collet7a225c02024-02-20 15:47:09 -0800524 cSizes[nbBlocks] = thisBlockSize;
Yann Collet9126da52018-11-08 12:47:46 -0800525 benchResult.cSize = thisBlockSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800526 }
527 }
528 }
529 }
Yann Collet1c00dc32015-10-21 08:22:25 +0100530
Josh Sorefa880ca22019-04-12 14:18:11 -0400531 /* warming up `compressedBuffer` */
George Lu85223462018-06-14 14:46:17 -0400532 if (adv->mode == BMK_decodeOnly) {
Yann Collet03e7e142018-03-05 13:50:07 -0800533 memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
534 } else {
535 RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
536 }
Yann Collet4856a002015-01-24 01:58:16 +0100537
Yann Colletbcfb7ad2023-01-12 19:00:27 -0800538 if (!UTIL_support_MT_measurements() && adv->nbWorkers > 1) {
Yann Collet7a225c02024-02-20 15:47:09 -0800539 OUTPUTLEVEL(
540 2,
541 "Warning : time measurements may be incorrect in multithreading mode... \n")
Yann Collet574ecbb2022-06-19 11:38:06 -0700542 }
Yann Collet574ecbb2022-06-19 11:38:06 -0700543
Yann Collet4856a002015-01-24 01:58:16 +0100544 /* Bench */
Yann Collet7a225c02024-02-20 15:47:09 -0800545 {
546 U64 const crcOrig = (adv->mode == BMK_decodeOnly)
547 ? 0
548 : XXH64(srcBuffer, srcSize, 0);
549#define NB_MARKS 4
Yann Collet2e45bad2018-08-23 14:21:18 -0700550 const char* marks[NB_MARKS] = { " |", " /", " =", " \\" };
Yann Collet7a225c02024-02-20 15:47:09 -0800551 U32 markNb = 0;
552 int compressionCompleted = (adv->mode == BMK_decodeOnly);
553 int decompressionCompleted = (adv->mode == BMK_compressOnly);
Yann Colletb830ccc2018-11-13 13:05:39 -0800554 BMK_benchParams_t cbp, dbp;
Yann Collet2e45bad2018-08-23 14:21:18 -0700555 BMK_initCCtxArgs cctxprep;
556 BMK_initDCtxArgs dctxprep;
Yann Colletb830ccc2018-11-13 13:05:39 -0800557
Yann Collet7a225c02024-02-20 15:47:09 -0800558 cbp.benchFn = local_defaultCompress; /* ZSTD_compress2 */
559 cbp.benchPayload = cctx;
560 cbp.initFn = local_initCCtx; /* BMK_initCCtx */
561 cbp.initPayload = &cctxprep;
562 cbp.errorFn = ZSTD_isError;
563 cbp.blockCount = nbBlocks;
564 cbp.srcBuffers = srcPtrs;
565 cbp.srcSizes = srcSizes;
566 cbp.dstBuffers = cPtrs;
Yann Colletb830ccc2018-11-13 13:05:39 -0800567 cbp.dstCapacities = cCapacities;
Yann Collet7a225c02024-02-20 15:47:09 -0800568 cbp.blockResults = cSizes;
Yann Colletb830ccc2018-11-13 13:05:39 -0800569
Yann Collet7a225c02024-02-20 15:47:09 -0800570 cctxprep.cctx = cctx;
571 cctxprep.dictBuffer = dictBuffer;
Yann Collet2e45bad2018-08-23 14:21:18 -0700572 cctxprep.dictBufferSize = dictBufferSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800573 cctxprep.cLevel = cLevel;
574 cctxprep.comprParams = comprParams;
575 cctxprep.adv = adv;
Yann Colletb830ccc2018-11-13 13:05:39 -0800576
Yann Collet7a225c02024-02-20 15:47:09 -0800577 dbp.benchFn = local_defaultDecompress;
578 dbp.benchPayload = dctx;
579 dbp.initFn = local_initDCtx;
580 dbp.initPayload = &dctxprep;
581 dbp.errorFn = ZSTD_isError;
582 dbp.blockCount = nbBlocks;
583 dbp.srcBuffers = (const void* const*)cPtrs;
584 dbp.srcSizes = cSizes;
585 dbp.dstBuffers = resPtrs;
Yann Colletb830ccc2018-11-13 13:05:39 -0800586 dbp.dstCapacities = resSizes;
Yann Collet7a225c02024-02-20 15:47:09 -0800587 dbp.blockResults = NULL;
Yann Colletb830ccc2018-11-13 13:05:39 -0800588
Yann Collet7a225c02024-02-20 15:47:09 -0800589 dctxprep.dctx = dctx;
590 dctxprep.dictBuffer = dictBuffer;
Yann Collet2e45bad2018-08-23 14:21:18 -0700591 dctxprep.dictBufferSize = dictBufferSize;
Yann Collet4856a002015-01-24 01:58:16 +0100592
Yann Collet7a225c02024-02-20 15:47:09 -0800593 OUTPUTLEVEL(2, "\r%70s\r", ""); /* blank line */
Yann Colleteab69222021-09-03 12:51:02 -0700594 assert(srcSize < UINT_MAX);
Yann Collet7a225c02024-02-20 15:47:09 -0800595 OUTPUTLEVEL(
596 2,
597 "%2s-%-17.17s :%10u -> \r",
598 marks[markNb],
599 displayName,
600 (unsigned)srcSize);
George Lu50d612f2018-06-25 15:01:03 -0700601
Yann Collet2e45bad2018-08-23 14:21:18 -0700602 while (!(compressionCompleted && decompressionCompleted)) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700603 if (!compressionCompleted) {
Yann Collet7a225c02024-02-20 15:47:09 -0800604 BMK_runOutcome_t const cOutcome =
605 BMK_benchTimedFn(timeStateCompress, cbp);
Yann Collet2e45bad2018-08-23 14:21:18 -0700606
Yann Collet2279f3d2018-08-24 17:28:38 -0700607 if (!BMK_isSuccessful_runOutcome(cOutcome)) {
Yann Collet6740f8f2023-02-07 10:02:09 -0800608 RETURN_ERROR(30, BMK_benchOutcome_t, "compression error");
George Lu50d612f2018-06-25 15:01:03 -0700609 }
610
Yann Collet7a225c02024-02-20 15:47:09 -0800611 {
612 BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome);
613 cSize = cResult.sumOfReturn;
Yann Colleteab69222021-09-03 12:51:02 -0700614 ratio = (double)srcSize / (double)cSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800615 {
616 BMK_benchResult_t newResult;
617 newResult.cSpeed =
618 (U64)((double)srcSize * TIMELOOP_NANOSEC
619 / cResult.nanoSecPerRun);
Yann Collet4da5bdf2018-08-23 18:04:50 -0700620 benchResult.cSize = cSize;
621 if (newResult.cSpeed > benchResult.cSpeed)
622 benchResult.cSpeed = newResult.cSpeed;
Yann Collet7a225c02024-02-20 15:47:09 -0800623 }
George Lua8eea992018-06-19 10:58:22 -0700624 }
Yann Collet7a225c02024-02-20 15:47:09 -0800625
626 {
627 int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
628 assert(cSize < UINT_MAX);
629 OUTPUTLEVEL(
630 2,
631 "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \r",
632 marks[markNb],
633 displayName,
634 (unsigned)srcSize,
635 (unsigned)cSize,
636 ratioAccuracy,
637 ratio,
638 benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,
639 (double)benchResult.cSpeed / MB_UNIT);
640 }
641 compressionCompleted =
642 BMK_isCompleted_TimedFn(timeStateCompress);
Yann Collet2e45bad2018-08-23 14:21:18 -0700643 }
George Lue89f1fb2018-08-14 14:44:47 -0700644
Yann Collet7a225c02024-02-20 15:47:09 -0800645 if (!decompressionCompleted) {
646 BMK_runOutcome_t const dOutcome =
647 BMK_benchTimedFn(timeStateDecompress, dbp);
Yann Collet2e45bad2018-08-23 14:21:18 -0700648
Yann Collet7a225c02024-02-20 15:47:09 -0800649 if (!BMK_isSuccessful_runOutcome(dOutcome)) {
Yann Collet58e70672023-02-07 08:47:39 -0800650 RETURN_ERROR(30, BMK_benchOutcome_t, "decompression error");
Yann Collet2e45bad2018-08-23 14:21:18 -0700651 }
652
Yann Collet7a225c02024-02-20 15:47:09 -0800653 {
654 BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);
655 U64 const newDSpeed =
656 (U64)((double)srcSize * TIMELOOP_NANOSEC
657 / dResult.nanoSecPerRun);
Yann Collet4da5bdf2018-08-23 18:04:50 -0700658 if (newDSpeed > benchResult.dSpeed)
659 benchResult.dSpeed = newDSpeed;
660 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700661
Yann Collet7a225c02024-02-20 15:47:09 -0800662 {
663 int const ratioAccuracy = (ratio < 10.) ? 3 : 2;
664 OUTPUTLEVEL(
665 2,
666 "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r",
667 marks[markNb],
668 displayName,
669 (unsigned)srcSize,
670 (unsigned)cSize,
671 ratioAccuracy,
672 ratio,
673 benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,
674 (double)benchResult.cSpeed / MB_UNIT,
Yann Collet4da5bdf2018-08-23 18:04:50 -0700675 (double)benchResult.dSpeed / MB_UNIT);
George Lua8eea992018-06-19 10:58:22 -0700676 }
Yann Collet7a225c02024-02-20 15:47:09 -0800677 decompressionCompleted =
678 BMK_isCompleted_TimedFn(timeStateDecompress);
Yann Colletdaebc7f2017-11-18 15:54:32 -0800679 }
Yann Collet7a225c02024-02-20 15:47:09 -0800680 markNb = (markNb + 1) % NB_MARKS;
681 } /* while (!(compressionCompleted && decompressionCompleted)) */
George Lu20f4f322018-06-12 15:54:43 -0400682
683 /* CRC Checking */
Yann Collet7a225c02024-02-20 15:47:09 -0800684 {
685 const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);
686 U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
687 if ((adv->mode == BMK_both) && (crcOrig != crcCheck)) {
George Lu20f4f322018-06-12 15:54:43 -0400688 size_t u;
Yann Collet8bed4012018-11-08 12:36:39 -0800689 DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n",
Yann Collet7a225c02024-02-20 15:47:09 -0800690 displayName,
691 (unsigned)crcOrig,
692 (unsigned)crcCheck);
693 for (u = 0; u < srcSize; u++) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700694 if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) {
Yann Colletededcfc2018-12-21 16:19:44 -0800695 unsigned segNb, bNb, pos;
George Lu20f4f322018-06-12 15:54:43 -0400696 size_t bacc = 0;
Yann Colletededcfc2018-12-21 16:19:44 -0800697 DISPLAY("Decoding error at pos %u ", (unsigned)u);
George Lu20f4f322018-06-12 15:54:43 -0400698 for (segNb = 0; segNb < nbBlocks; segNb++) {
Yann Collet7a225c02024-02-20 15:47:09 -0800699 if (bacc + srcSizes[segNb] > u)
700 break;
George Lu20f4f322018-06-12 15:54:43 -0400701 bacc += srcSizes[segNb];
702 }
703 pos = (U32)(u - bacc);
704 bNb = pos / (128 KB);
Yann Collet7a225c02024-02-20 15:47:09 -0800705 DISPLAY("(sample %u, block %u, pos %u) \n",
706 segNb,
707 bNb,
708 pos);
709 {
710 size_t const lowest = (u > 5) ? 5 : u;
Yann Colletb8701102019-01-25 15:11:50 -0800711 size_t n;
George Lu20f4f322018-06-12 15:54:43 -0400712 DISPLAY("origin: ");
Yann Collet7a225c02024-02-20 15:47:09 -0800713 for (n = lowest; n > 0; n--)
714 DISPLAY("%02X ",
715 ((const BYTE*)srcBuffer)[u - n]);
George Lu20f4f322018-06-12 15:54:43 -0400716 DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
Yann Collet7a225c02024-02-20 15:47:09 -0800717 for (n = 1; n < 3; n++)
718 DISPLAY("%02X ",
719 ((const BYTE*)srcBuffer)[u + n]);
George Lu20f4f322018-06-12 15:54:43 -0400720 DISPLAY(" \n");
721 DISPLAY("decode: ");
Yann Collet7a225c02024-02-20 15:47:09 -0800722 for (n = lowest; n > 0; n--)
723 DISPLAY("%02X ", resultBuffer[u - n]);
Yann Collet2e45bad2018-08-23 14:21:18 -0700724 DISPLAY(" :%02X: ", resultBuffer[u]);
Yann Collet7a225c02024-02-20 15:47:09 -0800725 for (n = 1; n < 3; n++)
726 DISPLAY("%02X ", resultBuffer[u + n]);
George Lu20f4f322018-06-12 15:54:43 -0400727 DISPLAY(" \n");
728 }
729 break;
730 }
Yann Collet7a225c02024-02-20 15:47:09 -0800731 if (u == srcSize - 1) { /* should never happen */
George Lu20f4f322018-06-12 15:54:43 -0400732 DISPLAY("no difference detected\n");
Yann Collet77e805e2018-08-21 18:19:27 -0700733 }
Yann Collet7a225c02024-02-20 15:47:09 -0800734 } /* for (u=0; u<srcSize; u++) */
735 } /* if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) */
736 } /* CRC Checking */
George Lu20f4f322018-06-12 15:54:43 -0400737
Yann Collet7a225c02024-02-20 15:47:09 -0800738 if (displayLevel
739 == 1) { /* hidden display mode -q, used by python speed benchmark */
Yann Collet1f9ec132018-08-23 16:03:30 -0700740 double const cSpeed = (double)benchResult.cSpeed / MB_UNIT;
741 double const dSpeed = (double)benchResult.dSpeed / MB_UNIT;
Yann Collet2e45bad2018-08-23 14:21:18 -0700742 if (adv->additionalParam) {
Yann Collet7a225c02024-02-20 15:47:09 -0800743 OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s (param=%d)\n",
744 cLevel,
745 (int)cSize,
746 ratio,
747 cSpeed,
748 dSpeed,
749 displayName,
750 adv->additionalParam);
Yann Collet2e45bad2018-08-23 14:21:18 -0700751 } else {
Yann Collet7a225c02024-02-20 15:47:09 -0800752 OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n",
753 cLevel,
754 (int)cSize,
755 ratio,
756 cSpeed,
757 dSpeed,
758 displayName);
Yann Collet2e45bad2018-08-23 14:21:18 -0700759 }
George Luab26f242018-06-21 11:16:53 -0700760 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700761
Yann Collet08ceda32021-09-04 00:52:44 -0700762 OUTPUTLEVEL(2, "%2i#\n", cLevel);
Yann Collet7a225c02024-02-20 15:47:09 -0800763 } /* Bench */
Yann Collet2e45bad2018-08-23 14:21:18 -0700764
Yann Collet7a225c02024-02-20 15:47:09 -0800765 benchResult.cMem =
766 (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx);
Yann Collet2e45bad2018-08-23 14:21:18 -0700767 return BMK_benchOutcome_setValidResult(benchResult);
George Lua8eea992018-06-19 10:58:22 -0700768}
Yann Collet4856a002015-01-24 01:58:16 +0100769
Yann Collet7a225c02024-02-20 15:47:09 -0800770BMK_benchOutcome_t BMK_benchMemAdvanced(
771 const void* srcBuffer,
772 size_t srcSize,
773 void* dstBuffer,
774 size_t dstCapacity,
775 const size_t* fileSizes,
776 unsigned nbFiles,
777 int cLevel,
778 const ZSTD_compressionParameters* comprParams,
779 const void* dictBuffer,
780 size_t dictBufferSize,
781 int displayLevel,
782 const char* displayName,
783 const BMK_advancedParams_t* adv)
George Lua8eea992018-06-19 10:58:22 -0700784
785{
Yann Collet7a225c02024-02-20 15:47:09 -0800786 int const dstParamsError =
787 !dstBuffer ^ !dstCapacity; /* must be both NULL or none */
Yann Collet2e45bad2018-08-23 14:21:18 -0700788
Yann Collet7a225c02024-02-20 15:47:09 -0800789 size_t const blockSize =
790 ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
791 ? adv->blockSize
792 : srcSize)
793 + (!srcSize) /* avoid div by 0 */;
794 U32 const maxNbBlocks =
795 (U32)((srcSize + (blockSize - 1)) / blockSize) + nbFiles;
George Lua8eea992018-06-19 10:58:22 -0700796
797 /* these are the blockTable parameters, just split up */
Yann Collet7a225c02024-02-20 15:47:09 -0800798 const void** const srcPtrs =
799 (const void**)malloc(maxNbBlocks * sizeof(void*));
George Ludd270b22018-07-27 08:49:25 -0700800 size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700801
Yann Collet7a225c02024-02-20 15:47:09 -0800802 void** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
803 size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Ludd270b22018-07-27 08:49:25 -0700804 size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700805
Yann Collet7a225c02024-02-20 15:47:09 -0800806 void** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
George Ludd270b22018-07-27 08:49:25 -0700807 size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700808
Yann Collet7a225c02024-02-20 15:47:09 -0800809 BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(
810 adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
811 BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(
812 adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
George Lud6121ad2018-06-22 17:25:16 -0700813
Yann Collet2e45bad2018-08-23 14:21:18 -0700814 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
815 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
George Lubfe83922018-08-09 12:07:57 -0700816
Yann Collet7a225c02024-02-20 15:47:09 -0800817 const size_t maxCompressedSize = dstCapacity
818 ? dstCapacity
819 : ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);
George Ludd270b22018-07-27 08:49:25 -0700820
Yann Collet7a225c02024-02-20 15:47:09 -0800821 void* const internalDstBuffer =
822 dstBuffer ? NULL : malloc(maxCompressedSize);
George Ludd270b22018-07-27 08:49:25 -0700823 void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer;
824
Yann Collet7a225c02024-02-20 15:47:09 -0800825 BMK_benchOutcome_t outcome =
826 BMK_benchOutcome_error(); /* error by default */
George Lue89f1fb2018-08-14 14:44:47 -0700827
828 void* resultBuffer = srcSize ? malloc(srcSize) : NULL;
829
Yann Collet7a225c02024-02-20 15:47:09 -0800830 int const allocationincomplete = !srcPtrs || !srcSizes || !cPtrs || !cSizes
831 || !cCapacities || !resPtrs || !resSizes || !timeStateCompress
832 || !timeStateDecompress || !cctx || !dctx || !compressedBuffer
833 || !resultBuffer;
George Lu5f490342018-06-18 11:59:45 -0700834
Yann Collet2e45bad2018-08-23 14:21:18 -0700835 if (!allocationincomplete && !dstParamsError) {
Yann Collet7a225c02024-02-20 15:47:09 -0800836 outcome = BMK_benchMemAdvancedNoAlloc(
837 srcPtrs,
838 srcSizes,
839 cPtrs,
840 cCapacities,
841 cSizes,
842 resPtrs,
843 resSizes,
844 &resultBuffer,
845 compressedBuffer,
846 maxCompressedSize,
847 timeStateCompress,
848 timeStateDecompress,
849 srcBuffer,
850 srcSize,
851 fileSizes,
852 nbFiles,
853 cLevel,
854 comprParams,
855 dictBuffer,
856 dictBufferSize,
857 cctx,
858 dctx,
859 displayLevel,
860 displayName,
861 adv);
George Lua8eea992018-06-19 10:58:22 -0700862 }
Yann Collet77e805e2018-08-21 18:19:27 -0700863
Yann Colleted699e62015-12-16 02:37:24 +0100864 /* clean up */
Yann Collet77e805e2018-08-21 18:19:27 -0700865 BMK_freeTimedFnState(timeStateCompress);
866 BMK_freeTimedFnState(timeStateDecompress);
867
Yann Collet2e45bad2018-08-23 14:21:18 -0700868 ZSTD_freeCCtx(cctx);
George Lubfe83922018-08-09 12:07:57 -0700869 ZSTD_freeDCtx(dctx);
870
George Ludd270b22018-07-27 08:49:25 -0700871 free(internalDstBuffer);
Yann Collet4856a002015-01-24 01:58:16 +0100872 free(resultBuffer);
George Lu20f4f322018-06-12 15:54:43 -0400873
Yann Collet77e805e2018-08-21 18:19:27 -0700874 free((void*)srcPtrs);
875 free(srcSizes);
876 free(cPtrs);
George Lu20f4f322018-06-12 15:54:43 -0400877 free(cSizes);
George Lue148db32018-07-20 14:35:09 -0700878 free(cCapacities);
George Lu20f4f322018-06-12 15:54:43 -0400879 free(resPtrs);
880 free(resSizes);
881
Yann Collet7a225c02024-02-20 15:47:09 -0800882 if (allocationincomplete) {
883 RETURN_ERROR(
884 31, BMK_benchOutcome_t, "allocation error : not enough memory");
George Lua8eea992018-06-19 10:58:22 -0700885 }
Yann Collet77e805e2018-08-21 18:19:27 -0700886
Yann Collet7a225c02024-02-20 15:47:09 -0800887 if (dstParamsError) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700888 RETURN_ERROR(32, BMK_benchOutcome_t, "Dst parameters not coherent");
George Ludd270b22018-07-27 08:49:25 -0700889 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700890 return outcome;
Yann Collet4856a002015-01-24 01:58:16 +0100891}
892
Yann Collet7a225c02024-02-20 15:47:09 -0800893BMK_benchOutcome_t BMK_benchMem(
894 const void* srcBuffer,
895 size_t srcSize,
896 const size_t* fileSizes,
897 unsigned nbFiles,
898 int cLevel,
899 const ZSTD_compressionParameters* comprParams,
900 const void* dictBuffer,
901 size_t dictBufferSize,
902 int displayLevel,
903 const char* displayName)
904{
Yann Collet2e45bad2018-08-23 14:21:18 -0700905 BMK_advancedParams_t const adv = BMK_initAdvancedParams();
Yann Collet7a225c02024-02-20 15:47:09 -0800906 return BMK_benchMemAdvanced(
907 srcBuffer,
908 srcSize,
909 NULL,
910 0,
911 fileSizes,
912 nbFiles,
913 cLevel,
914 comprParams,
915 dictBuffer,
916 dictBufferSize,
917 displayLevel,
918 displayName,
919 &adv);
George Lu20f4f322018-06-12 15:54:43 -0400920}
921
Yann Collet7a225c02024-02-20 15:47:09 -0800922static BMK_benchOutcome_t BMK_benchCLevel(
923 const void* srcBuffer,
924 size_t benchedSize,
925 const size_t* fileSizes,
926 unsigned nbFiles,
927 int cLevel,
928 const ZSTD_compressionParameters* comprParams,
929 const void* dictBuffer,
930 size_t dictBufferSize,
931 int displayLevel,
932 const char* displayName,
933 BMK_advancedParams_t const* const adv)
Yann Collet2e45bad2018-08-23 14:21:18 -0700934{
935 const char* pch = strrchr(displayName, '\\'); /* Windows */
Yann Collet7a225c02024-02-20 15:47:09 -0800936 if (!pch)
937 pch = strrchr(displayName, '/'); /* Linux */
938 if (pch)
939 displayName = pch + 1;
Yann Collet2e45bad2018-08-23 14:21:18 -0700940
941 if (adv->realTime) {
942 DISPLAYLEVEL(2, "Note : switching to real-time priority \n");
943 SET_REALTIME_PRIORITY;
944 }
945
Yann Collet7a225c02024-02-20 15:47:09 -0800946 if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */
Yann Collet08ceda32021-09-04 00:52:44 -0700947 OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n",
Yann Collet7a225c02024-02-20 15:47:09 -0800948 ZSTD_VERSION_STRING,
949 ZSTD_GIT_COMMIT_STRING,
950 (unsigned)benchedSize,
951 adv->nbSeconds,
952 (unsigned)(adv->blockSize >> 10));
Yann Collet2e45bad2018-08-23 14:21:18 -0700953
Yann Collet7a225c02024-02-20 15:47:09 -0800954 return BMK_benchMemAdvanced(
955 srcBuffer,
956 benchedSize,
957 NULL,
958 0,
959 fileSizes,
960 nbFiles,
961 cLevel,
962 comprParams,
963 dictBuffer,
964 dictBufferSize,
965 displayLevel,
966 displayName,
967 adv);
Yann Collet2e45bad2018-08-23 14:21:18 -0700968}
969
Yann Collet7a225c02024-02-20 15:47:09 -0800970int BMK_syntheticTest(
971 int cLevel,
972 double compressibility,
973 const ZSTD_compressionParameters* compressionParams,
974 int displayLevel,
975 const BMK_advancedParams_t* adv)
Yann Collet2e45bad2018-08-23 14:21:18 -0700976{
Yann Collet7a225c02024-02-20 15:47:09 -0800977 char nameBuff[20] = { 0 };
978 const char* name = nameBuff;
979 size_t const benchedSize = adv->blockSize ? adv->blockSize : 10000000;
Yann Collet2e45bad2018-08-23 14:21:18 -0700980 void* srcBuffer;
981 BMK_benchOutcome_t res;
982
983 if (cLevel > ZSTD_maxCLevel()) {
Yann Colletdb792192023-03-06 12:15:22 -0800984 DISPLAYLEVEL(1, "Invalid Compression Level");
985 return 15;
Yann Collet2e45bad2018-08-23 14:21:18 -0700986 }
987
988 /* Memory allocation */
989 srcBuffer = malloc(benchedSize);
Yann Colletdb792192023-03-06 12:15:22 -0800990 if (!srcBuffer) {
991 DISPLAYLEVEL(1, "allocation error : not enough memory");
992 return 16;
993 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700994
995 /* Fill input buffer */
Yann Colletd0b7da32024-01-29 15:00:32 -0800996 if (compressibility < 0.0) {
997 LOREM_genBuffer(srcBuffer, benchedSize, 0);
998 name = "Lorem ipsum";
999 } else {
1000 RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);
Yann Collet588dfbc2024-02-20 19:21:01 -08001001 formatString_u(
Yann Collet7a225c02024-02-20 15:47:09 -08001002 nameBuff,
1003 sizeof(nameBuff),
Yann Collet588dfbc2024-02-20 19:21:01 -08001004 "Synthetic %u%%",
Yann Collet7a225c02024-02-20 15:47:09 -08001005 (unsigned)(compressibility * 100));
Yann Colletd0b7da32024-01-29 15:00:32 -08001006 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001007
1008 /* Bench */
Yann Collet7a225c02024-02-20 15:47:09 -08001009 res = BMK_benchCLevel(
1010 srcBuffer,
1011 benchedSize,
1012 &benchedSize /* ? */,
1013 1 /* ? */,
1014 cLevel,
1015 compressionParams,
1016 NULL,
1017 0, /* dictionary */
1018 displayLevel,
1019 name,
1020 adv);
Yann Collet2e45bad2018-08-23 14:21:18 -07001021
1022 /* clean up */
1023 free(srcBuffer);
1024
Yann Colletdb792192023-03-06 12:15:22 -08001025 return !BMK_isSuccessful_benchOutcome(res);
Yann Collet2e45bad2018-08-23 14:21:18 -07001026}
1027
Yann Collet4856a002015-01-24 01:58:16 +01001028static size_t BMK_findMaxMem(U64 requiredMem)
1029{
Yann Colletde406ee2016-03-20 15:46:10 +01001030 size_t const step = 64 MB;
Yann Collet7a225c02024-02-20 15:47:09 -08001031 BYTE* testmem = NULL;
Yann Collet4856a002015-01-24 01:58:16 +01001032
1033 requiredMem = (((requiredMem >> 26) + 1) << 26);
Yann Colletde406ee2016-03-20 15:46:10 +01001034 requiredMem += step;
Yann Collet7a225c02024-02-20 15:47:09 -08001035 if (requiredMem > maxMemory)
1036 requiredMem = maxMemory;
Yann Collet4856a002015-01-24 01:58:16 +01001037
Yann Colletde406ee2016-03-20 15:46:10 +01001038 do {
Yann Collet4856a002015-01-24 01:58:16 +01001039 testmem = (BYTE*)malloc((size_t)requiredMem);
Yann Colletde406ee2016-03-20 15:46:10 +01001040 requiredMem -= step;
George Lue89f1fb2018-08-14 14:44:47 -07001041 } while (!testmem && requiredMem > 0);
Yann Colletde406ee2016-03-20 15:46:10 +01001042
Yann Collet4856a002015-01-24 01:58:16 +01001043 free(testmem);
Yann Colletde406ee2016-03-20 15:46:10 +01001044 return (size_t)(requiredMem);
Yann Collet4856a002015-01-24 01:58:16 +01001045}
1046
Yann Colleta5b66e32016-03-26 01:48:27 +01001047/*! BMK_loadFiles() :
Yann Collet6a9b41b2018-03-11 19:56:48 -07001048 * Loads `buffer` with content of files listed within `fileNamesTable`.
1049 * At most, fills `buffer` entirely. */
Yann Collet7a225c02024-02-20 15:47:09 -08001050static int BMK_loadFiles(
1051 void* buffer,
1052 size_t bufferSize,
1053 size_t* fileSizes,
1054 const char* const* fileNamesTable,
1055 unsigned nbFiles,
1056 int displayLevel)
Yann Colleted699e62015-12-16 02:37:24 +01001057{
inikepc0d5f4e2016-04-13 10:48:04 +02001058 size_t pos = 0, totalSize = 0;
Yann Collet699b14d2016-03-17 19:37:33 +01001059 unsigned n;
Yann Collet7a225c02024-02-20 15:47:09 -08001060 for (n = 0; n < nbFiles; n++) {
1061 U64 fileSize = UTIL_getFileSize(
1062 fileNamesTable[n]); /* last file may be shortened */
inikep69fcd7c2016-04-28 12:23:33 +02001063 if (UTIL_isDirectory(fileNamesTable[n])) {
Yann Collet7a225c02024-02-20 15:47:09 -08001064 DISPLAYLEVEL(
1065 2, "Ignoring %s directory... \n", fileNamesTable[n]);
inikepbab43172016-04-29 15:19:40 +02001066 fileSizes[n] = 0;
inikepc0d5f4e2016-04-13 10:48:04 +02001067 continue;
1068 }
Yann Collet18b79532017-10-17 16:14:25 -07001069 if (fileSize == UTIL_FILESIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -08001070 DISPLAYLEVEL(
1071 2,
1072 "Cannot evaluate size of %s, ignoring ... \n",
1073 fileNamesTable[n]);
Yann Collet18b79532017-10-17 16:14:25 -07001074 fileSizes[n] = 0;
1075 continue;
1076 }
Yann Collet7a225c02024-02-20 15:47:09 -08001077 {
1078 FILE* const f = fopen(fileNamesTable[n], "rb");
1079 if (f == NULL)
1080 RETURN_ERROR_INT(
1081 10, "impossible to open file %s", fileNamesTable[n]);
Yann Collet08ceda32021-09-04 00:52:44 -07001082 OUTPUTLEVEL(2, "Loading %s... \r", fileNamesTable[n]);
Yann Collet7a225c02024-02-20 15:47:09 -08001083 if (fileSize > bufferSize - pos)
1084 fileSize = bufferSize - pos,
1085 nbFiles = n; /* buffer too small - stop after this file */
1086 {
1087 size_t const readSize =
1088 fread(((char*)buffer) + pos, 1, (size_t)fileSize, f);
1089 if (readSize != (size_t)fileSize)
1090 RETURN_ERROR_INT(
1091 11, "could not read %s", fileNamesTable[n]);
Yann Collet6309be62019-10-15 16:09:18 -07001092 pos += readSize;
1093 }
1094 fileSizes[n] = (size_t)fileSize;
1095 totalSize += (size_t)fileSize;
1096 fclose(f);
Yann Collet7a225c02024-02-20 15:47:09 -08001097 }
1098 }
Yann Collet6f9c0562016-05-01 10:26:30 +02001099
Yann Collet7a225c02024-02-20 15:47:09 -08001100 if (totalSize == 0)
1101 RETURN_ERROR_INT(12, "no data to bench");
George Lu20f4f322018-06-12 15:54:43 -04001102 return 0;
Yann Colleted699e62015-12-16 02:37:24 +01001103}
1104
Yann Collet1e38e072023-03-06 12:34:13 -08001105int BMK_benchFilesAdvanced(
Yann Collet7a225c02024-02-20 15:47:09 -08001106 const char* const* fileNamesTable,
1107 unsigned nbFiles,
1108 const char* dictFileName,
1109 int cLevel,
1110 const ZSTD_compressionParameters* compressionParams,
1111 int displayLevel,
1112 const BMK_advancedParams_t* adv)
Yann Colleted699e62015-12-16 02:37:24 +01001113{
George Lud6121ad2018-06-22 17:25:16 -07001114 void* srcBuffer = NULL;
Yann Colleted699e62015-12-16 02:37:24 +01001115 size_t benchedSize;
Yann Collet7a225c02024-02-20 15:47:09 -08001116 void* dictBuffer = NULL;
Yann Collet31683c02015-12-18 01:26:48 +01001117 size_t dictBufferSize = 0;
Yann Collet7a225c02024-02-20 15:47:09 -08001118 size_t* fileSizes = NULL;
Yann Colletc3a4baa2018-08-24 21:38:09 -07001119 BMK_benchOutcome_t res;
Yann Collete162ace2016-05-20 11:24:35 +02001120 U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
Yann Colleted699e62015-12-16 02:37:24 +01001121
Yann Collet2e45bad2018-08-23 14:21:18 -07001122 if (!nbFiles) {
Yann Collet1e38e072023-03-06 12:34:13 -08001123 DISPLAYLEVEL(1, "No Files to Benchmark");
1124 return 13;
George Lua8eea992018-06-19 10:58:22 -07001125 }
Yann Collet31683c02015-12-18 01:26:48 +01001126
George Lua8eea992018-06-19 10:58:22 -07001127 if (cLevel > ZSTD_maxCLevel()) {
Yann Collet1e38e072023-03-06 12:34:13 -08001128 DISPLAYLEVEL(1, "Invalid Compression Level");
1129 return 14;
George Lua8eea992018-06-19 10:58:22 -07001130 }
1131
senhuang42dce48f52021-08-23 19:10:16 -04001132 if (totalSizeToLoad == UTIL_FILESIZE_UNKNOWN) {
Yann Collet1e38e072023-03-06 12:34:13 -08001133 DISPLAYLEVEL(1, "Error loading files");
1134 return 15;
senhuang42dce48f52021-08-23 19:10:16 -04001135 }
1136
George Lua8eea992018-06-19 10:58:22 -07001137 fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t));
Yann Collet1e38e072023-03-06 12:34:13 -08001138 if (!fileSizes) {
1139 DISPLAYLEVEL(1, "not enough memory for fileSizes");
1140 return 16;
1141 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001142
Yann Collet31683c02015-12-18 01:26:48 +01001143 /* Load dictionary */
Yann Colletfd416f12016-01-30 03:14:15 +01001144 if (dictFileName != NULL) {
Yann Collet18b79532017-10-17 16:14:25 -07001145 U64 const dictFileSize = UTIL_getFileSize(dictFileName);
Yann Colleted2fb6b2018-12-20 17:20:07 -08001146 if (dictFileSize == UTIL_FILESIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -08001147 DISPLAYLEVEL(
1148 1,
1149 "error loading %s : %s \n",
1150 dictFileName,
1151 strerror(errno));
Yann Colleted2fb6b2018-12-20 17:20:07 -08001152 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001153 DISPLAYLEVEL(1, "benchmark aborted");
1154 return 17;
Yann Colleted2fb6b2018-12-20 17:20:07 -08001155 }
George Lua8eea992018-06-19 10:58:22 -07001156 if (dictFileSize > 64 MB) {
1157 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001158 DISPLAYLEVEL(1, "dictionary file %s too large", dictFileName);
1159 return 18;
George Lua8eea992018-06-19 10:58:22 -07001160 }
Yann Collet31683c02015-12-18 01:26:48 +01001161 dictBufferSize = (size_t)dictFileSize;
Yann Collet7a225c02024-02-20 15:47:09 -08001162 dictBuffer = malloc(dictBufferSize);
1163 if (dictBuffer == NULL) {
George Lua8eea992018-06-19 10:58:22 -07001164 free(fileSizes);
Yann Collet7a225c02024-02-20 15:47:09 -08001165 DISPLAYLEVEL(
1166 1,
1167 "not enough memory for dictionary (%u bytes)",
1168 (unsigned)dictBufferSize);
Yann Collet1e38e072023-03-06 12:34:13 -08001169 return 19;
George Lua8eea992018-06-19 10:58:22 -07001170 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001171
Yann Collet7a225c02024-02-20 15:47:09 -08001172 {
1173 int const errorCode = BMK_loadFiles(
1174 dictBuffer,
1175 dictBufferSize,
1176 fileSizes,
1177 &dictFileName /*?*/,
1178 1 /*?*/,
1179 displayLevel);
Yann Collet2e45bad2018-08-23 14:21:18 -07001180 if (errorCode) {
1181 res = BMK_benchOutcome_error();
George Lud6121ad2018-06-22 17:25:16 -07001182 goto _cleanUp;
Yann Collet7a225c02024-02-20 15:47:09 -08001183 }
1184 }
Yann Collet31683c02015-12-18 01:26:48 +01001185 }
1186
Yann Colleted699e62015-12-16 02:37:24 +01001187 /* Memory allocation & restrictions */
1188 benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;
Yann Collet7a225c02024-02-20 15:47:09 -08001189 if ((U64)benchedSize > totalSizeToLoad)
1190 benchedSize = (size_t)totalSizeToLoad;
Yann Colleted699e62015-12-16 02:37:24 +01001191 if (benchedSize < totalSizeToLoad)
Yann Collet7a225c02024-02-20 15:47:09 -08001192 DISPLAY("Not enough memory; testing %u MB only...\n",
1193 (unsigned)(benchedSize >> 20));
George Lue89f1fb2018-08-14 14:44:47 -07001194
1195 srcBuffer = benchedSize ? malloc(benchedSize) : NULL;
George Lua8eea992018-06-19 10:58:22 -07001196 if (!srcBuffer) {
1197 free(dictBuffer);
1198 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001199 DISPLAYLEVEL(1, "not enough memory for srcBuffer");
1200 return 20;
George Lua8eea992018-06-19 10:58:22 -07001201 }
Yann Colleted699e62015-12-16 02:37:24 +01001202
1203 /* Load input buffer */
Yann Collet7a225c02024-02-20 15:47:09 -08001204 {
1205 int const errorCode = BMK_loadFiles(
1206 srcBuffer,
1207 benchedSize,
1208 fileSizes,
1209 fileNamesTable,
1210 nbFiles,
1211 displayLevel);
Yann Collet2e45bad2018-08-23 14:21:18 -07001212 if (errorCode) {
1213 res = BMK_benchOutcome_error();
George Lud6121ad2018-06-22 17:25:16 -07001214 goto _cleanUp;
Yann Collet7a225c02024-02-20 15:47:09 -08001215 }
1216 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001217
Yann Colleted699e62015-12-16 02:37:24 +01001218 /* Bench */
Yann Collet7a225c02024-02-20 15:47:09 -08001219 {
1220 char mfName[20] = { 0 };
Yann Collet588dfbc2024-02-20 19:21:01 -08001221 formatString_u(mfName, sizeof(mfName), " %u files", nbFiles);
Yann Collet7a225c02024-02-20 15:47:09 -08001222 {
1223 const char* const displayName =
1224 (nbFiles > 1) ? mfName : fileNamesTable[0];
1225 res = BMK_benchCLevel(
1226 srcBuffer,
1227 benchedSize,
1228 fileSizes,
1229 nbFiles,
1230 cLevel,
1231 compressionParams,
1232 dictBuffer,
1233 dictBufferSize,
1234 displayLevel,
1235 displayName,
1236 adv);
1237 }
1238 }
Yann Collet4856a002015-01-24 01:58:16 +01001239
George Lud6121ad2018-06-22 17:25:16 -07001240_cleanUp:
Yann Collet4856a002015-01-24 01:58:16 +01001241 free(srcBuffer);
Yann Collet31683c02015-12-18 01:26:48 +01001242 free(dictBuffer);
Yann Collet70611352015-12-16 03:01:03 +01001243 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001244 return !BMK_isSuccessful_benchOutcome(res);
Yann Collet4856a002015-01-24 01:58:16 +01001245}
1246
Yann Collet7a225c02024-02-20 15:47:09 -08001247int BMK_benchFiles(
1248 const char* const* fileNamesTable,
1249 unsigned nbFiles,
1250 const char* dictFileName,
1251 int cLevel,
1252 const ZSTD_compressionParameters* compressionParams,
1253 int displayLevel)
Yann Collet4856a002015-01-24 01:58:16 +01001254{
Yann Collet2e45bad2018-08-23 14:21:18 -07001255 BMK_advancedParams_t const adv = BMK_initAdvancedParams();
Yann Collet7a225c02024-02-20 15:47:09 -08001256 return BMK_benchFilesAdvanced(
1257 fileNamesTable,
1258 nbFiles,
1259 dictFileName,
1260 cLevel,
1261 compressionParams,
1262 displayLevel,
1263 &adv);
Yann Collet4856a002015-01-24 01:58:16 +01001264}