blob: f9274a5172c1815881436c93781adc5061bbf1c8 [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 Collet89451ca2024-08-06 11:44:37 -0700142static size_t uintSize(unsigned value)
143{
144 size_t size = 1;
145 while (value >= 10) {
146 size++;
147 value /= 10;
148 }
149 return size;
150}
151
Yann Collet14b8d392024-08-06 12:47:30 -0700152/* Note: presume @buffer is large enough */
Yann Collet89451ca2024-08-06 11:44:37 -0700153static void writeUint_varLen(char* buffer, size_t capacity, unsigned value)
154{
155 int endPos = (int)uintSize(value) - 1;
156 assert(uintSize(value) >= 1);
157 assert(uintSize(value) < capacity); (void)capacity;
158 while (endPos >= 0) {
159 char c = '0' + (char)(value % 10);
160 buffer[endPos--] = c;
161 value /= 10;
162 }
163}
164
165/* replacement for snprintf(), which is not supported by C89.
166 * sprintf() would be the supported one, but it's labelled unsafe:
167 * modern static analyzer will flag sprintf() as dangerous, making it unusable.
168 * formatString_u() replaces snprintf() for the specific case where there is only one %u argument */
Yann Collete62e15d2024-02-20 22:43:22 -0800169static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value)
Yann Collet588dfbc2024-02-20 19:21:01 -0800170{
Yann Collet89451ca2024-08-06 11:44:37 -0700171 size_t const valueSize = uintSize(value);
Yann Collet588dfbc2024-02-20 19:21:01 -0800172 size_t written = 0;
173 int i;
Yann Collet588dfbc2024-02-20 19:21:01 -0800174
Yann Collet89451ca2024-08-06 11:44:37 -0700175 for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; i++) {
Yann Collet588dfbc2024-02-20 19:21:01 -0800176 if (formatString[i] != '%') {
177 buffer[written++] = formatString[i];
178 continue;
179 }
180
Yann Collet89451ca2024-08-06 11:44:37 -0700181 i++;
182 if (formatString[i] == 'u') {
183 if (written + valueSize >= buffer_size) abort(); /* buffer not large enough */
184 writeUint_varLen(buffer + written, buffer_size - written, value);
185 written += valueSize;
Yann Collet588dfbc2024-02-20 19:21:01 -0800186 } else if (formatString[i] == '%') { /* Check for escaped percent sign */
187 buffer[written++] = '%';
188 } else {
Yann Collet89451ca2024-08-06 11:44:37 -0700189 abort(); /* unsupported format */
Yann Collet588dfbc2024-02-20 19:21:01 -0800190 }
191 }
192
193 if (written < buffer_size) {
194 buffer[written] = '\0';
195 } else {
Yann Collet89451ca2024-08-06 11:44:37 -0700196 abort(); /* buffer not large enough */
Yann Collet588dfbc2024-02-20 19:21:01 -0800197 }
198
Yann Collete62e15d2024-02-20 22:43:22 -0800199 return (int)written;
Yann Collet588dfbc2024-02-20 19:21:01 -0800200}
201
Yann Colletf3eca252015-10-22 15:31:46 +0100202/* *************************************
Yann Collet7a225c02024-02-20 15:47:09 -0800203 * Benchmark Parameters
204 ***************************************/
Stella Laua1f04d52017-09-01 14:52:51 -0700205
Yann Collet7a225c02024-02-20 15:47:09 -0800206BMK_advancedParams_t BMK_initAdvancedParams(void)
207{
Yann Collet2e45bad2018-08-23 14:21:18 -0700208 BMK_advancedParams_t const res = {
Yann Collet7a225c02024-02-20 15:47:09 -0800209 BMK_both, /* mode */
George Lu20f4f322018-06-12 15:54:43 -0400210 BMK_TIMETEST_DEFAULT_S, /* nbSeconds */
Yann Collet7a225c02024-02-20 15:47:09 -0800211 0, /* blockSize */
Yann Collet68a232c2024-02-23 13:13:03 -0800212 0, /* targetCBlockSize */
Yann Collet7a225c02024-02-20 15:47:09 -0800213 0, /* nbWorkers */
214 0, /* realTime */
215 0, /* additionalParam */
216 0, /* ldmFlag */
217 0, /* ldmMinMatch */
218 0, /* ldmHashLog */
219 0, /* ldmBuckSizeLog */
220 0, /* ldmHashRateLog */
221 ZSTD_ps_auto, /* literalCompressionMode */
222 0 /* useRowMatchFinder */
George Lu20f4f322018-06-12 15:54:43 -0400223 };
224 return res;
Stella Lau67d4a612017-09-02 21:10:36 -0700225}
226
Yann Colletf3eca252015-10-22 15:31:46 +0100227/* ********************************************************
Yann Collet7a225c02024-02-20 15:47:09 -0800228 * Bench functions
229 **********************************************************/
Yann Colletd9465012016-12-06 16:49:23 -0800230typedef struct {
231 const void* srcPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100232 size_t srcSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800233 void* cPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100234 size_t cRoom;
235 size_t cSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800236 void* resPtr;
Yann Collet1c00dc32015-10-21 08:22:25 +0100237 size_t resSize;
238} blockParam_t;
239
Sean Purcell42bac7f2017-04-13 15:35:05 -0700240#undef MIN
241#undef MAX
Yann Collet7a225c02024-02-20 15:47:09 -0800242#define MIN(a, b) ((a) < (b) ? (a) : (b))
243#define MAX(a, b) ((a) > (b) ? (a) : (b))
Yann Collet1c00dc32015-10-21 08:22:25 +0100244
Yann Collet7a225c02024-02-20 15:47:09 -0800245static void BMK_initCCtx(
246 ZSTD_CCtx* ctx,
247 const void* dictBuffer,
248 size_t dictBufferSize,
249 int cLevel,
250 const ZSTD_compressionParameters* comprParams,
251 const BMK_advancedParams_t* adv)
Yann Colletb8701102019-01-25 15:11:50 -0800252{
Yann Collet5c686392018-11-15 16:12:39 -0800253 ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);
Yann Collet7a225c02024-02-20 15:47:09 -0800254 if (adv->nbWorkers == 1) {
Yann Colletd613fd92018-12-06 19:27:37 -0800255 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));
George Lu20f4f322018-06-12 15:54:43 -0400256 } else {
Yann Colletd613fd92018-12-06 19:27:37 -0800257 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers));
George Lu20f4f322018-06-12 15:54:43 -0400258 }
Yann Colletd613fd92018-12-06 19:27:37 -0800259 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel));
Yann Collet7a225c02024-02-20 15:47:09 -0800260 CHECK_Z(ZSTD_CCtx_setParameter(
261 ctx, ZSTD_c_useRowMatchFinder, adv->useRowMatchFinder));
262 CHECK_Z(ZSTD_CCtx_setParameter(
263 ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag));
Yann Colletd613fd92018-12-06 19:27:37 -0800264 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch));
265 CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));
Yann Collet7a225c02024-02-20 15:47:09 -0800266 CHECK_Z(ZSTD_CCtx_setParameter(
267 ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));
268 CHECK_Z(ZSTD_CCtx_setParameter(
269 ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));
270 CHECK_Z(ZSTD_CCtx_setParameter(
271 ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));
272 CHECK_Z(ZSTD_CCtx_setParameter(
273 ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));
274 CHECK_Z(ZSTD_CCtx_setParameter(
275 ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));
276 CHECK_Z(ZSTD_CCtx_setParameter(
277 ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));
278 CHECK_Z(ZSTD_CCtx_setParameter(
279 ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));
280 CHECK_Z(ZSTD_CCtx_setParameter(
281 ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));
282 CHECK_Z(ZSTD_CCtx_setParameter(
283 ctx,
284 ZSTD_c_literalCompressionMode,
285 (int)adv->literalCompressionMode));
286 CHECK_Z(ZSTD_CCtx_setParameter(
287 ctx, ZSTD_c_strategy, (int)comprParams->strategy));
Yann Collet68a232c2024-02-23 13:13:03 -0800288 CHECK_Z(ZSTD_CCtx_setParameter(
289 ctx, ZSTD_c_targetCBlockSize, (int)adv->targetCBlockSize));
Yann Colletd613fd92018-12-06 19:27:37 -0800290 CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));
George Lu20f4f322018-06-12 15:54:43 -0400291}
292
Yann Collet7a225c02024-02-20 15:47:09 -0800293static void
294BMK_initDCtx(ZSTD_DCtx* dctx, const void* dictBuffer, size_t dictBufferSize)
295{
Yann Colletd613fd92018-12-06 19:27:37 -0800296 CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));
297 CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize));
George Lu20f4f322018-06-12 15:54:43 -0400298}
299
300typedef struct {
Yann Collet2e45bad2018-08-23 14:21:18 -0700301 ZSTD_CCtx* cctx;
George Lu20f4f322018-06-12 15:54:43 -0400302 const void* dictBuffer;
303 size_t dictBufferSize;
304 int cLevel;
305 const ZSTD_compressionParameters* comprParams;
306 const BMK_advancedParams_t* adv;
307} BMK_initCCtxArgs;
308
Yann Collet7a225c02024-02-20 15:47:09 -0800309static size_t local_initCCtx(void* payload)
310{
George Lu20f4f322018-06-12 15:54:43 -0400311 BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload;
Yann Collet7a225c02024-02-20 15:47:09 -0800312 BMK_initCCtx(
313 ag->cctx,
314 ag->dictBuffer,
315 ag->dictBufferSize,
316 ag->cLevel,
317 ag->comprParams,
318 ag->adv);
George Lu20f4f322018-06-12 15:54:43 -0400319 return 0;
320}
321
322typedef struct {
323 ZSTD_DCtx* dctx;
324 const void* dictBuffer;
325 size_t dictBufferSize;
326} BMK_initDCtxArgs;
327
Yann Collet7a225c02024-02-20 15:47:09 -0800328static size_t local_initDCtx(void* payload)
329{
George Lu20f4f322018-06-12 15:54:43 -0400330 BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload;
331 BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize);
332 return 0;
333}
334
Yann Collet2e45bad2018-08-23 14:21:18 -0700335/* `addArgs` is the context */
George Lu20f4f322018-06-12 15:54:43 -0400336static size_t local_defaultCompress(
Yann Collet7a225c02024-02-20 15:47:09 -0800337 const void* srcBuffer,
338 size_t srcSize,
339 void* dstBuffer,
340 size_t dstSize,
341 void* addArgs)
Yann Collet2e45bad2018-08-23 14:21:18 -0700342{
Yann Collet2e45bad2018-08-23 14:21:18 -0700343 ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs;
Yann Colletd8e215c2018-11-30 11:16:26 -0800344 return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize);
George Lu20f4f322018-06-12 15:54:43 -0400345}
346
Yann Collet2e45bad2018-08-23 14:21:18 -0700347/* `addArgs` is the context */
George Lu20f4f322018-06-12 15:54:43 -0400348static size_t local_defaultDecompress(
Yann Collet7a225c02024-02-20 15:47:09 -0800349 const void* srcBuffer,
350 size_t srcSize,
351 void* dstBuffer,
352 size_t dstCapacity,
353 void* addArgs)
Yann Collet2e45bad2018-08-23 14:21:18 -0700354{
Yann Collet7a225c02024-02-20 15:47:09 -0800355 size_t moreToFlush = 1;
Yann Collet2e45bad2018-08-23 14:21:18 -0700356 ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs;
George Lu20f4f322018-06-12 15:54:43 -0400357 ZSTD_inBuffer in;
358 ZSTD_outBuffer out;
Yann Collet7a225c02024-02-20 15:47:09 -0800359 in.src = srcBuffer;
360 in.size = srcSize;
361 in.pos = 0;
362 out.dst = dstBuffer;
363 out.size = dstCapacity;
364 out.pos = 0;
George Lu20f4f322018-06-12 15:54:43 -0400365 while (moreToFlush) {
Yann Collet7a225c02024-02-20 15:47:09 -0800366 if (out.pos == out.size) {
George Lud6121ad2018-06-22 17:25:16 -0700367 return (size_t)-ZSTD_error_dstSize_tooSmall;
368 }
Yann Collet34e146f2018-12-04 10:28:36 -0800369 moreToFlush = ZSTD_decompressStream(dctx, &out, &in);
George Lu20f4f322018-06-12 15:54:43 -0400370 if (ZSTD_isError(moreToFlush)) {
371 return moreToFlush;
372 }
373 }
374 return out.pos;
George Lu20f4f322018-06-12 15:54:43 -0400375}
376
Yann Collet2e45bad2018-08-23 14:21:18 -0700377/* ================================================================= */
378/* Benchmark Zstandard, mem-to-mem scenarios */
379/* ================================================================= */
380
381int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome)
382{
383 return outcome.tag == 0;
384}
385
386BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome)
387{
388 assert(outcome.tag == 0);
389 return outcome.internal_never_use_directly;
390}
391
Yann Collet6ce7b082018-08-24 15:59:57 -0700392static BMK_benchOutcome_t BMK_benchOutcome_error(void)
Yann Collet2e45bad2018-08-23 14:21:18 -0700393{
394 BMK_benchOutcome_t b;
395 memset(&b, 0, sizeof(b));
396 b.tag = 1;
397 return b;
398}
399
Yann Collet7a225c02024-02-20 15:47:09 -0800400static BMK_benchOutcome_t BMK_benchOutcome_setValidResult(
401 BMK_benchResult_t result)
Yann Collet2e45bad2018-08-23 14:21:18 -0700402{
403 BMK_benchOutcome_t b;
Yann Collet7a225c02024-02-20 15:47:09 -0800404 b.tag = 0;
Yann Collet2e45bad2018-08-23 14:21:18 -0700405 b.internal_never_use_directly = result;
406 return b;
407}
408
Yann Collet2e45bad2018-08-23 14:21:18 -0700409/* benchMem with no allocation */
Yann Collet7a225c02024-02-20 15:47:09 -0800410static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(
411 const void** srcPtrs,
412 size_t* srcSizes,
413 void** cPtrs,
414 size_t* cCapacities,
415 size_t* cSizes,
416 void** resPtrs,
417 size_t* resSizes,
418 void** resultBufferPtr,
419 void* compressedBuffer,
420 size_t maxCompressedSize,
421 BMK_timedFnState_t* timeStateCompress,
422 BMK_timedFnState_t* timeStateDecompress,
Yann Collet2e45bad2018-08-23 14:21:18 -0700423
Yann Collet7a225c02024-02-20 15:47:09 -0800424 const void* srcBuffer,
425 size_t srcSize,
426 const size_t* fileSizes,
427 unsigned nbFiles,
428 const int cLevel,
429 const ZSTD_compressionParameters* comprParams,
430 const void* dictBuffer,
431 size_t dictBufferSize,
432 ZSTD_CCtx* cctx,
433 ZSTD_DCtx* dctx,
434 int displayLevel,
435 const char* displayName,
436 const BMK_advancedParams_t* adv)
Yann Collet1c00dc32015-10-21 08:22:25 +0100437{
Yann Collet7a225c02024-02-20 15:47:09 -0800438 size_t const blockSize =
439 ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
440 ? adv->blockSize
441 : srcSize)
442 + (!srcSize); /* avoid div by 0 */
Yann Collet2e45bad2018-08-23 14:21:18 -0700443 BMK_benchResult_t benchResult;
Yann Collete63c6312016-12-06 17:46:49 -0800444 size_t const loadedCompressedSize = srcSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800445 size_t cSize = 0;
446 double ratio = 0.;
Yann Colletde406ee2016-03-20 15:46:10 +0100447 U32 nbBlocks;
448
Yann Collet7a225c02024-02-20 15:47:09 -0800449 assert(cctx != NULL);
450 assert(dctx != NULL);
George Lu01d940b2018-06-11 10:59:05 -0400451
Yann Colletc776c462015-10-29 19:10:54 +0100452 /* init */
Yann Collet4da5bdf2018-08-23 18:04:50 -0700453 memset(&benchResult, 0, sizeof(benchResult));
Yann Collet7a225c02024-02-20 15:47:09 -0800454 if (strlen(displayName) > 17)
455 displayName +=
456 strlen(displayName) - 17; /* display last 17 characters */
Yann Collet58e70672023-02-07 08:47:39 -0800457 if (adv->mode == BMK_decodeOnly) {
458 /* benchmark only decompression : source must be already compressed */
Yann Colletc2007382017-04-04 15:35:06 -0700459 const char* srcPtr = (const char*)srcBuffer;
Yann Collet7a225c02024-02-20 15:47:09 -0800460 U64 totalDSize64 = 0;
Yann Collete63c6312016-12-06 17:46:49 -0800461 U32 fileNb;
Yann Collet7a225c02024-02-20 15:47:09 -0800462 for (fileNb = 0; fileNb < nbFiles; fileNb++) {
463 U64 const fSize64 =
464 ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]);
Yann Collet58e70672023-02-07 08:47:39 -0800465 if (fSize64 == ZSTD_CONTENTSIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -0800466 RETURN_ERROR(
467 32,
468 BMK_benchOutcome_t,
469 "Decompressed size cannot be determined: cannot benchmark");
Yann Collet58e70672023-02-07 08:47:39 -0800470 }
471 if (fSize64 == ZSTD_CONTENTSIZE_ERROR) {
Yann Collet7a225c02024-02-20 15:47:09 -0800472 RETURN_ERROR(
473 32,
474 BMK_benchOutcome_t,
475 "Error while trying to assess decompressed size: data may be invalid");
Yann Collet58e70672023-02-07 08:47:39 -0800476 }
Yann Colletc2007382017-04-04 15:35:06 -0700477 totalDSize64 += fSize64;
Yann Collete63c6312016-12-06 17:46:49 -0800478 srcPtr += fileSizes[fileNb];
479 }
Yann Collet7a225c02024-02-20 15:47:09 -0800480 {
481 size_t const decodedSize = (size_t)totalDSize64;
482 assert((U64)decodedSize == totalDSize64); /* check overflow */
George Lu5f490342018-06-18 11:59:45 -0700483 free(*resultBufferPtr);
Yann Collet7a225c02024-02-20 15:47:09 -0800484 if (totalDSize64 > decodedSize) { /* size_t overflow */
485 RETURN_ERROR(
486 32,
487 BMK_benchOutcome_t,
488 "decompressed size is too large for local system");
Yann Collet58e70672023-02-07 08:47:39 -0800489 }
George Lu5f490342018-06-18 11:59:45 -0700490 *resultBufferPtr = malloc(decodedSize);
491 if (!(*resultBufferPtr)) {
Yann Collet7a225c02024-02-20 15:47:09 -0800492 RETURN_ERROR(
493 33,
494 BMK_benchOutcome_t,
495 "allocation error: not enough memory");
George Lua8eea992018-06-19 10:58:22 -0700496 }
Yann Collet7a225c02024-02-20 15:47:09 -0800497 cSize = srcSize;
Yann Collete63c6312016-12-06 17:46:49 -0800498 srcSize = decodedSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800499 ratio = (double)srcSize / (double)cSize;
Yann Collet77e805e2018-08-21 18:19:27 -0700500 }
George Lu20f4f322018-06-12 15:54:43 -0400501 }
Yann Collete63c6312016-12-06 17:46:49 -0800502
George Lu20f4f322018-06-12 15:54:43 -0400503 /* Init data blocks */
Yann Collet7a225c02024-02-20 15:47:09 -0800504 {
505 const char* srcPtr = (const char*)srcBuffer;
506 char* cPtr = (char*)compressedBuffer;
507 char* resPtr = (char*)(*resultBufferPtr);
Yann Collet699b14d2016-03-17 19:37:33 +0100508 U32 fileNb;
Yann Collet7a225c02024-02-20 15:47:09 -0800509 for (nbBlocks = 0, fileNb = 0; fileNb < nbFiles; fileNb++) {
510 size_t remaining = fileSizes[fileNb];
511 U32 const nbBlocksforThisFile = (adv->mode == BMK_decodeOnly)
512 ? 1
513 : (U32)((remaining + (blockSize - 1)) / blockSize);
514 U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
515 for (; nbBlocks < blockEnd; nbBlocks++) {
Yann Colletde406ee2016-03-20 15:46:10 +0100516 size_t const thisBlockSize = MIN(remaining, blockSize);
Yann Collet7a225c02024-02-20 15:47:09 -0800517 srcPtrs[nbBlocks] = srcPtr;
518 srcSizes[nbBlocks] = thisBlockSize;
519 cPtrs[nbBlocks] = cPtr;
520 cCapacities[nbBlocks] = (adv->mode == BMK_decodeOnly)
521 ? thisBlockSize
522 : ZSTD_compressBound(thisBlockSize);
523 resPtrs[nbBlocks] = resPtr;
524 resSizes[nbBlocks] = (adv->mode == BMK_decodeOnly)
525 ? (size_t)ZSTD_findDecompressedSize(
526 srcPtr, thisBlockSize)
527 : thisBlockSize;
Yann Colleted699e62015-12-16 02:37:24 +0100528 srcPtr += thisBlockSize;
George Lue148db32018-07-20 14:35:09 -0700529 cPtr += cCapacities[nbBlocks];
Yann Colleted699e62015-12-16 02:37:24 +0100530 resPtr += thisBlockSize;
531 remaining -= thisBlockSize;
Yann Collet3ba0d6d2018-11-13 14:15:12 -0800532 if (adv->mode == BMK_decodeOnly) {
Yann Collet7a225c02024-02-20 15:47:09 -0800533 cSizes[nbBlocks] = thisBlockSize;
Yann Collet9126da52018-11-08 12:47:46 -0800534 benchResult.cSize = thisBlockSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800535 }
536 }
537 }
538 }
Yann Collet1c00dc32015-10-21 08:22:25 +0100539
Josh Sorefa880ca22019-04-12 14:18:11 -0400540 /* warming up `compressedBuffer` */
George Lu85223462018-06-14 14:46:17 -0400541 if (adv->mode == BMK_decodeOnly) {
Yann Collet03e7e142018-03-05 13:50:07 -0800542 memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
543 } else {
544 RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
545 }
Yann Collet4856a002015-01-24 01:58:16 +0100546
Yann Colletbcfb7ad2023-01-12 19:00:27 -0800547 if (!UTIL_support_MT_measurements() && adv->nbWorkers > 1) {
Yann Collet7a225c02024-02-20 15:47:09 -0800548 OUTPUTLEVEL(
549 2,
550 "Warning : time measurements may be incorrect in multithreading mode... \n")
Yann Collet574ecbb2022-06-19 11:38:06 -0700551 }
Yann Collet574ecbb2022-06-19 11:38:06 -0700552
Yann Collet4856a002015-01-24 01:58:16 +0100553 /* Bench */
Yann Collet7a225c02024-02-20 15:47:09 -0800554 {
555 U64 const crcOrig = (adv->mode == BMK_decodeOnly)
556 ? 0
557 : XXH64(srcBuffer, srcSize, 0);
558#define NB_MARKS 4
Yann Collet2e45bad2018-08-23 14:21:18 -0700559 const char* marks[NB_MARKS] = { " |", " /", " =", " \\" };
Yann Collet7a225c02024-02-20 15:47:09 -0800560 U32 markNb = 0;
561 int compressionCompleted = (adv->mode == BMK_decodeOnly);
562 int decompressionCompleted = (adv->mode == BMK_compressOnly);
Yann Colletb830ccc2018-11-13 13:05:39 -0800563 BMK_benchParams_t cbp, dbp;
Yann Collet2e45bad2018-08-23 14:21:18 -0700564 BMK_initCCtxArgs cctxprep;
565 BMK_initDCtxArgs dctxprep;
Yann Colletb830ccc2018-11-13 13:05:39 -0800566
Yann Collet7a225c02024-02-20 15:47:09 -0800567 cbp.benchFn = local_defaultCompress; /* ZSTD_compress2 */
568 cbp.benchPayload = cctx;
569 cbp.initFn = local_initCCtx; /* BMK_initCCtx */
570 cbp.initPayload = &cctxprep;
571 cbp.errorFn = ZSTD_isError;
572 cbp.blockCount = nbBlocks;
573 cbp.srcBuffers = srcPtrs;
574 cbp.srcSizes = srcSizes;
575 cbp.dstBuffers = cPtrs;
Yann Colletb830ccc2018-11-13 13:05:39 -0800576 cbp.dstCapacities = cCapacities;
Yann Collet7a225c02024-02-20 15:47:09 -0800577 cbp.blockResults = cSizes;
Yann Colletb830ccc2018-11-13 13:05:39 -0800578
Yann Collet7a225c02024-02-20 15:47:09 -0800579 cctxprep.cctx = cctx;
580 cctxprep.dictBuffer = dictBuffer;
Yann Collet2e45bad2018-08-23 14:21:18 -0700581 cctxprep.dictBufferSize = dictBufferSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800582 cctxprep.cLevel = cLevel;
583 cctxprep.comprParams = comprParams;
584 cctxprep.adv = adv;
Yann Colletb830ccc2018-11-13 13:05:39 -0800585
Yann Collet7a225c02024-02-20 15:47:09 -0800586 dbp.benchFn = local_defaultDecompress;
587 dbp.benchPayload = dctx;
588 dbp.initFn = local_initDCtx;
589 dbp.initPayload = &dctxprep;
590 dbp.errorFn = ZSTD_isError;
591 dbp.blockCount = nbBlocks;
592 dbp.srcBuffers = (const void* const*)cPtrs;
593 dbp.srcSizes = cSizes;
594 dbp.dstBuffers = resPtrs;
Yann Colletb830ccc2018-11-13 13:05:39 -0800595 dbp.dstCapacities = resSizes;
Yann Collet7a225c02024-02-20 15:47:09 -0800596 dbp.blockResults = NULL;
Yann Colletb830ccc2018-11-13 13:05:39 -0800597
Yann Collet7a225c02024-02-20 15:47:09 -0800598 dctxprep.dctx = dctx;
599 dctxprep.dictBuffer = dictBuffer;
Yann Collet2e45bad2018-08-23 14:21:18 -0700600 dctxprep.dictBufferSize = dictBufferSize;
Yann Collet4856a002015-01-24 01:58:16 +0100601
Yann Collet7a225c02024-02-20 15:47:09 -0800602 OUTPUTLEVEL(2, "\r%70s\r", ""); /* blank line */
Yann Colleteab69222021-09-03 12:51:02 -0700603 assert(srcSize < UINT_MAX);
Yann Collet7a225c02024-02-20 15:47:09 -0800604 OUTPUTLEVEL(
605 2,
606 "%2s-%-17.17s :%10u -> \r",
607 marks[markNb],
608 displayName,
609 (unsigned)srcSize);
George Lu50d612f2018-06-25 15:01:03 -0700610
Yann Collet2e45bad2018-08-23 14:21:18 -0700611 while (!(compressionCompleted && decompressionCompleted)) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700612 if (!compressionCompleted) {
Yann Collet7a225c02024-02-20 15:47:09 -0800613 BMK_runOutcome_t const cOutcome =
614 BMK_benchTimedFn(timeStateCompress, cbp);
Yann Collet2e45bad2018-08-23 14:21:18 -0700615
Yann Collet2279f3d2018-08-24 17:28:38 -0700616 if (!BMK_isSuccessful_runOutcome(cOutcome)) {
Yann Collet6740f8f2023-02-07 10:02:09 -0800617 RETURN_ERROR(30, BMK_benchOutcome_t, "compression error");
George Lu50d612f2018-06-25 15:01:03 -0700618 }
619
Yann Collet7a225c02024-02-20 15:47:09 -0800620 {
621 BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome);
622 cSize = cResult.sumOfReturn;
Yann Colleteab69222021-09-03 12:51:02 -0700623 ratio = (double)srcSize / (double)cSize;
Yann Collet7a225c02024-02-20 15:47:09 -0800624 {
625 BMK_benchResult_t newResult;
626 newResult.cSpeed =
627 (U64)((double)srcSize * TIMELOOP_NANOSEC
628 / cResult.nanoSecPerRun);
Yann Collet4da5bdf2018-08-23 18:04:50 -0700629 benchResult.cSize = cSize;
630 if (newResult.cSpeed > benchResult.cSpeed)
631 benchResult.cSpeed = newResult.cSpeed;
Yann Collet7a225c02024-02-20 15:47:09 -0800632 }
George Lua8eea992018-06-19 10:58:22 -0700633 }
Yann Collet7a225c02024-02-20 15:47:09 -0800634
635 {
Yann Collet60f84f72025-01-30 21:30:48 -0800636 int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.);
Yann Collet7a225c02024-02-20 15:47:09 -0800637 assert(cSize < UINT_MAX);
638 OUTPUTLEVEL(
639 2,
640 "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \r",
641 marks[markNb],
642 displayName,
643 (unsigned)srcSize,
644 (unsigned)cSize,
Yann Collet60f84f72025-01-30 21:30:48 -0800645 ratioDigits,
Yann Collet7a225c02024-02-20 15:47:09 -0800646 ratio,
647 benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,
648 (double)benchResult.cSpeed / MB_UNIT);
649 }
650 compressionCompleted =
651 BMK_isCompleted_TimedFn(timeStateCompress);
Yann Collet2e45bad2018-08-23 14:21:18 -0700652 }
George Lue89f1fb2018-08-14 14:44:47 -0700653
Yann Collet7a225c02024-02-20 15:47:09 -0800654 if (!decompressionCompleted) {
655 BMK_runOutcome_t const dOutcome =
656 BMK_benchTimedFn(timeStateDecompress, dbp);
Yann Collet2e45bad2018-08-23 14:21:18 -0700657
Yann Collet7a225c02024-02-20 15:47:09 -0800658 if (!BMK_isSuccessful_runOutcome(dOutcome)) {
Yann Collet58e70672023-02-07 08:47:39 -0800659 RETURN_ERROR(30, BMK_benchOutcome_t, "decompression error");
Yann Collet2e45bad2018-08-23 14:21:18 -0700660 }
661
Yann Collet7a225c02024-02-20 15:47:09 -0800662 {
663 BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);
664 U64 const newDSpeed =
665 (U64)((double)srcSize * TIMELOOP_NANOSEC
666 / dResult.nanoSecPerRun);
Yann Collet4da5bdf2018-08-23 18:04:50 -0700667 if (newDSpeed > benchResult.dSpeed)
668 benchResult.dSpeed = newDSpeed;
669 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700670
Yann Collet7a225c02024-02-20 15:47:09 -0800671 {
Yann Collet60f84f72025-01-30 21:30:48 -0800672 int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.);
Yann Collet7a225c02024-02-20 15:47:09 -0800673 OUTPUTLEVEL(
674 2,
675 "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r",
676 marks[markNb],
677 displayName,
678 (unsigned)srcSize,
679 (unsigned)cSize,
Yann Collet60f84f72025-01-30 21:30:48 -0800680 ratioDigits,
Yann Collet7a225c02024-02-20 15:47:09 -0800681 ratio,
682 benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,
683 (double)benchResult.cSpeed / MB_UNIT,
Yann Collet4da5bdf2018-08-23 18:04:50 -0700684 (double)benchResult.dSpeed / MB_UNIT);
George Lua8eea992018-06-19 10:58:22 -0700685 }
Yann Collet7a225c02024-02-20 15:47:09 -0800686 decompressionCompleted =
687 BMK_isCompleted_TimedFn(timeStateDecompress);
Yann Colletdaebc7f2017-11-18 15:54:32 -0800688 }
Yann Collet7a225c02024-02-20 15:47:09 -0800689 markNb = (markNb + 1) % NB_MARKS;
690 } /* while (!(compressionCompleted && decompressionCompleted)) */
George Lu20f4f322018-06-12 15:54:43 -0400691
692 /* CRC Checking */
Yann Collet7a225c02024-02-20 15:47:09 -0800693 {
694 const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);
695 U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
696 if ((adv->mode == BMK_both) && (crcOrig != crcCheck)) {
George Lu20f4f322018-06-12 15:54:43 -0400697 size_t u;
Yann Collet8bed4012018-11-08 12:36:39 -0800698 DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n",
Yann Collet7a225c02024-02-20 15:47:09 -0800699 displayName,
700 (unsigned)crcOrig,
701 (unsigned)crcCheck);
702 for (u = 0; u < srcSize; u++) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700703 if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) {
Yann Colletededcfc2018-12-21 16:19:44 -0800704 unsigned segNb, bNb, pos;
George Lu20f4f322018-06-12 15:54:43 -0400705 size_t bacc = 0;
Yann Colletededcfc2018-12-21 16:19:44 -0800706 DISPLAY("Decoding error at pos %u ", (unsigned)u);
George Lu20f4f322018-06-12 15:54:43 -0400707 for (segNb = 0; segNb < nbBlocks; segNb++) {
Yann Collet7a225c02024-02-20 15:47:09 -0800708 if (bacc + srcSizes[segNb] > u)
709 break;
George Lu20f4f322018-06-12 15:54:43 -0400710 bacc += srcSizes[segNb];
711 }
712 pos = (U32)(u - bacc);
713 bNb = pos / (128 KB);
Yann Collet7a225c02024-02-20 15:47:09 -0800714 DISPLAY("(sample %u, block %u, pos %u) \n",
715 segNb,
716 bNb,
717 pos);
718 {
719 size_t const lowest = (u > 5) ? 5 : u;
Yann Colletb8701102019-01-25 15:11:50 -0800720 size_t n;
George Lu20f4f322018-06-12 15:54:43 -0400721 DISPLAY("origin: ");
Yann Collet7a225c02024-02-20 15:47:09 -0800722 for (n = lowest; n > 0; n--)
723 DISPLAY("%02X ",
724 ((const BYTE*)srcBuffer)[u - n]);
George Lu20f4f322018-06-12 15:54:43 -0400725 DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]);
Yann Collet7a225c02024-02-20 15:47:09 -0800726 for (n = 1; n < 3; n++)
727 DISPLAY("%02X ",
728 ((const BYTE*)srcBuffer)[u + n]);
George Lu20f4f322018-06-12 15:54:43 -0400729 DISPLAY(" \n");
730 DISPLAY("decode: ");
Yann Collet7a225c02024-02-20 15:47:09 -0800731 for (n = lowest; n > 0; n--)
732 DISPLAY("%02X ", resultBuffer[u - n]);
Yann Collet2e45bad2018-08-23 14:21:18 -0700733 DISPLAY(" :%02X: ", resultBuffer[u]);
Yann Collet7a225c02024-02-20 15:47:09 -0800734 for (n = 1; n < 3; n++)
735 DISPLAY("%02X ", resultBuffer[u + n]);
George Lu20f4f322018-06-12 15:54:43 -0400736 DISPLAY(" \n");
737 }
738 break;
739 }
Yann Collet7a225c02024-02-20 15:47:09 -0800740 if (u == srcSize - 1) { /* should never happen */
George Lu20f4f322018-06-12 15:54:43 -0400741 DISPLAY("no difference detected\n");
Yann Collet77e805e2018-08-21 18:19:27 -0700742 }
Yann Collet7a225c02024-02-20 15:47:09 -0800743 } /* for (u=0; u<srcSize; u++) */
744 } /* if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) */
745 } /* CRC Checking */
George Lu20f4f322018-06-12 15:54:43 -0400746
Yann Collet7a225c02024-02-20 15:47:09 -0800747 if (displayLevel
748 == 1) { /* hidden display mode -q, used by python speed benchmark */
Yann Collet1f9ec132018-08-23 16:03:30 -0700749 double const cSpeed = (double)benchResult.cSpeed / MB_UNIT;
750 double const dSpeed = (double)benchResult.dSpeed / MB_UNIT;
Yann Collet2e45bad2018-08-23 14:21:18 -0700751 if (adv->additionalParam) {
Yann Collet7a225c02024-02-20 15:47:09 -0800752 OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s (param=%d)\n",
753 cLevel,
754 (int)cSize,
755 ratio,
756 cSpeed,
757 dSpeed,
758 displayName,
759 adv->additionalParam);
Yann Collet2e45bad2018-08-23 14:21:18 -0700760 } else {
Yann Collet7a225c02024-02-20 15:47:09 -0800761 OUTPUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n",
762 cLevel,
763 (int)cSize,
764 ratio,
765 cSpeed,
766 dSpeed,
767 displayName);
Yann Collet2e45bad2018-08-23 14:21:18 -0700768 }
George Luab26f242018-06-21 11:16:53 -0700769 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700770
Yann Collet08ceda32021-09-04 00:52:44 -0700771 OUTPUTLEVEL(2, "%2i#\n", cLevel);
Yann Collet7a225c02024-02-20 15:47:09 -0800772 } /* Bench */
Yann Collet2e45bad2018-08-23 14:21:18 -0700773
Yann Collet7a225c02024-02-20 15:47:09 -0800774 benchResult.cMem =
775 (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx);
Yann Collet2e45bad2018-08-23 14:21:18 -0700776 return BMK_benchOutcome_setValidResult(benchResult);
George Lua8eea992018-06-19 10:58:22 -0700777}
Yann Collet4856a002015-01-24 01:58:16 +0100778
Yann Collet7a225c02024-02-20 15:47:09 -0800779BMK_benchOutcome_t BMK_benchMemAdvanced(
780 const void* srcBuffer,
781 size_t srcSize,
782 void* dstBuffer,
783 size_t dstCapacity,
784 const size_t* fileSizes,
785 unsigned nbFiles,
786 int cLevel,
787 const ZSTD_compressionParameters* comprParams,
788 const void* dictBuffer,
789 size_t dictBufferSize,
790 int displayLevel,
791 const char* displayName,
792 const BMK_advancedParams_t* adv)
George Lua8eea992018-06-19 10:58:22 -0700793
794{
Yann Collet7a225c02024-02-20 15:47:09 -0800795 int const dstParamsError =
796 !dstBuffer ^ !dstCapacity; /* must be both NULL or none */
Yann Collet2e45bad2018-08-23 14:21:18 -0700797
Yann Collet7a225c02024-02-20 15:47:09 -0800798 size_t const blockSize =
799 ((adv->blockSize >= 32 && (adv->mode != BMK_decodeOnly))
800 ? adv->blockSize
801 : srcSize)
802 + (!srcSize) /* avoid div by 0 */;
803 U32 const maxNbBlocks =
804 (U32)((srcSize + (blockSize - 1)) / blockSize) + nbFiles;
George Lua8eea992018-06-19 10:58:22 -0700805
806 /* these are the blockTable parameters, just split up */
Yann Collet7a225c02024-02-20 15:47:09 -0800807 const void** const srcPtrs =
808 (const void**)malloc(maxNbBlocks * sizeof(void*));
George Ludd270b22018-07-27 08:49:25 -0700809 size_t* const srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700810
Yann Collet7a225c02024-02-20 15:47:09 -0800811 void** const cPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
812 size_t* const cSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Ludd270b22018-07-27 08:49:25 -0700813 size_t* const cCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700814
Yann Collet7a225c02024-02-20 15:47:09 -0800815 void** const resPtrs = (void**)malloc(maxNbBlocks * sizeof(void*));
George Ludd270b22018-07-27 08:49:25 -0700816 size_t* const resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));
George Lua8eea992018-06-19 10:58:22 -0700817
Yann Collet7a225c02024-02-20 15:47:09 -0800818 BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(
819 adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
820 BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(
821 adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);
George Lud6121ad2018-06-22 17:25:16 -0700822
Yann Collet2e45bad2018-08-23 14:21:18 -0700823 ZSTD_CCtx* const cctx = ZSTD_createCCtx();
824 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
George Lubfe83922018-08-09 12:07:57 -0700825
Yann Collet7a225c02024-02-20 15:47:09 -0800826 const size_t maxCompressedSize = dstCapacity
827 ? dstCapacity
828 : ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);
George Ludd270b22018-07-27 08:49:25 -0700829
Yann Collet7a225c02024-02-20 15:47:09 -0800830 void* const internalDstBuffer =
831 dstBuffer ? NULL : malloc(maxCompressedSize);
George Ludd270b22018-07-27 08:49:25 -0700832 void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer;
833
Yann Collet7a225c02024-02-20 15:47:09 -0800834 BMK_benchOutcome_t outcome =
835 BMK_benchOutcome_error(); /* error by default */
George Lue89f1fb2018-08-14 14:44:47 -0700836
837 void* resultBuffer = srcSize ? malloc(srcSize) : NULL;
838
Yann Collet7a225c02024-02-20 15:47:09 -0800839 int const allocationincomplete = !srcPtrs || !srcSizes || !cPtrs || !cSizes
840 || !cCapacities || !resPtrs || !resSizes || !timeStateCompress
841 || !timeStateDecompress || !cctx || !dctx || !compressedBuffer
842 || !resultBuffer;
George Lu5f490342018-06-18 11:59:45 -0700843
Yann Collet2e45bad2018-08-23 14:21:18 -0700844 if (!allocationincomplete && !dstParamsError) {
Yann Collet7a225c02024-02-20 15:47:09 -0800845 outcome = BMK_benchMemAdvancedNoAlloc(
846 srcPtrs,
847 srcSizes,
848 cPtrs,
849 cCapacities,
850 cSizes,
851 resPtrs,
852 resSizes,
853 &resultBuffer,
854 compressedBuffer,
855 maxCompressedSize,
856 timeStateCompress,
857 timeStateDecompress,
858 srcBuffer,
859 srcSize,
860 fileSizes,
861 nbFiles,
862 cLevel,
863 comprParams,
864 dictBuffer,
865 dictBufferSize,
866 cctx,
867 dctx,
868 displayLevel,
869 displayName,
870 adv);
George Lua8eea992018-06-19 10:58:22 -0700871 }
Yann Collet77e805e2018-08-21 18:19:27 -0700872
Yann Colleted699e62015-12-16 02:37:24 +0100873 /* clean up */
Yann Collet77e805e2018-08-21 18:19:27 -0700874 BMK_freeTimedFnState(timeStateCompress);
875 BMK_freeTimedFnState(timeStateDecompress);
876
Yann Collet2e45bad2018-08-23 14:21:18 -0700877 ZSTD_freeCCtx(cctx);
George Lubfe83922018-08-09 12:07:57 -0700878 ZSTD_freeDCtx(dctx);
879
George Ludd270b22018-07-27 08:49:25 -0700880 free(internalDstBuffer);
Yann Collet4856a002015-01-24 01:58:16 +0100881 free(resultBuffer);
George Lu20f4f322018-06-12 15:54:43 -0400882
Yann Collet77e805e2018-08-21 18:19:27 -0700883 free((void*)srcPtrs);
884 free(srcSizes);
885 free(cPtrs);
George Lu20f4f322018-06-12 15:54:43 -0400886 free(cSizes);
George Lue148db32018-07-20 14:35:09 -0700887 free(cCapacities);
George Lu20f4f322018-06-12 15:54:43 -0400888 free(resPtrs);
889 free(resSizes);
890
Yann Collet7a225c02024-02-20 15:47:09 -0800891 if (allocationincomplete) {
892 RETURN_ERROR(
893 31, BMK_benchOutcome_t, "allocation error : not enough memory");
George Lua8eea992018-06-19 10:58:22 -0700894 }
Yann Collet77e805e2018-08-21 18:19:27 -0700895
Yann Collet7a225c02024-02-20 15:47:09 -0800896 if (dstParamsError) {
Yann Collet2e45bad2018-08-23 14:21:18 -0700897 RETURN_ERROR(32, BMK_benchOutcome_t, "Dst parameters not coherent");
George Ludd270b22018-07-27 08:49:25 -0700898 }
Yann Collet2e45bad2018-08-23 14:21:18 -0700899 return outcome;
Yann Collet4856a002015-01-24 01:58:16 +0100900}
901
Yann Collet7a225c02024-02-20 15:47:09 -0800902BMK_benchOutcome_t BMK_benchMem(
903 const void* srcBuffer,
904 size_t srcSize,
905 const size_t* fileSizes,
906 unsigned nbFiles,
907 int cLevel,
908 const ZSTD_compressionParameters* comprParams,
909 const void* dictBuffer,
910 size_t dictBufferSize,
911 int displayLevel,
912 const char* displayName)
913{
Yann Collet2e45bad2018-08-23 14:21:18 -0700914 BMK_advancedParams_t const adv = BMK_initAdvancedParams();
Yann Collet7a225c02024-02-20 15:47:09 -0800915 return BMK_benchMemAdvanced(
916 srcBuffer,
917 srcSize,
918 NULL,
919 0,
920 fileSizes,
921 nbFiles,
922 cLevel,
923 comprParams,
924 dictBuffer,
925 dictBufferSize,
926 displayLevel,
927 displayName,
928 &adv);
George Lu20f4f322018-06-12 15:54:43 -0400929}
930
Yann Collet0079d512024-10-22 02:18:48 -0700931/* @return: 0 on success, !0 if error */
932static int BMK_benchCLevels(
Yann Collet7a225c02024-02-20 15:47:09 -0800933 const void* srcBuffer,
934 size_t benchedSize,
935 const size_t* fileSizes,
936 unsigned nbFiles,
Yann Collet0079d512024-10-22 02:18:48 -0700937 int startCLevel, int endCLevel,
Yann Collet7a225c02024-02-20 15:47:09 -0800938 const ZSTD_compressionParameters* comprParams,
939 const void* dictBuffer,
940 size_t dictBufferSize,
941 int displayLevel,
942 const char* displayName,
943 BMK_advancedParams_t const* const adv)
Yann Collet2e45bad2018-08-23 14:21:18 -0700944{
Yann Collet0079d512024-10-22 02:18:48 -0700945 int level;
Yann Collet2e45bad2018-08-23 14:21:18 -0700946 const char* pch = strrchr(displayName, '\\'); /* Windows */
Yann Collet7a225c02024-02-20 15:47:09 -0800947 if (!pch)
948 pch = strrchr(displayName, '/'); /* Linux */
949 if (pch)
950 displayName = pch + 1;
Yann Collet2e45bad2018-08-23 14:21:18 -0700951
Yann Collet0079d512024-10-22 02:18:48 -0700952 if (endCLevel > ZSTD_maxCLevel()) {
953 DISPLAYLEVEL(1, "Invalid Compression Level \n");
954 return 15;
955 }
956 if (endCLevel < startCLevel) {
957 DISPLAYLEVEL(1, "Invalid Compression Level Range \n");
958 return 15;
959 }
960
Yann Collet2e45bad2018-08-23 14:21:18 -0700961 if (adv->realTime) {
962 DISPLAYLEVEL(2, "Note : switching to real-time priority \n");
963 SET_REALTIME_PRIORITY;
964 }
965
Yann Collet7a225c02024-02-20 15:47:09 -0800966 if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */
Yann Collet08ceda32021-09-04 00:52:44 -0700967 OUTPUT("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n",
Yann Collet7a225c02024-02-20 15:47:09 -0800968 ZSTD_VERSION_STRING,
969 ZSTD_GIT_COMMIT_STRING,
970 (unsigned)benchedSize,
971 adv->nbSeconds,
972 (unsigned)(adv->blockSize >> 10));
Yann Collet2e45bad2018-08-23 14:21:18 -0700973
Yann Collet0079d512024-10-22 02:18:48 -0700974 for (level = startCLevel; level <= endCLevel; level++) {
975 BMK_benchOutcome_t res = BMK_benchMemAdvanced(
Yann Collet7a225c02024-02-20 15:47:09 -0800976 srcBuffer,
977 benchedSize,
978 NULL,
979 0,
980 fileSizes,
981 nbFiles,
Yann Collet0079d512024-10-22 02:18:48 -0700982 level,
Yann Collet7a225c02024-02-20 15:47:09 -0800983 comprParams,
984 dictBuffer,
985 dictBufferSize,
986 displayLevel,
987 displayName,
988 adv);
Yann Collet0079d512024-10-22 02:18:48 -0700989 if (!BMK_isSuccessful_benchOutcome(res)) return 1;
990 }
991 return 0;
Yann Collet2e45bad2018-08-23 14:21:18 -0700992}
993
Yann Collet7a225c02024-02-20 15:47:09 -0800994int BMK_syntheticTest(
Yann Collet7a225c02024-02-20 15:47:09 -0800995 double compressibility,
Yann Collet0079d512024-10-22 02:18:48 -0700996 int startingCLevel, int endCLevel,
Yann Collet7a225c02024-02-20 15:47:09 -0800997 const ZSTD_compressionParameters* compressionParams,
998 int displayLevel,
999 const BMK_advancedParams_t* adv)
Yann Collet2e45bad2018-08-23 14:21:18 -07001000{
Yann Collet7a225c02024-02-20 15:47:09 -08001001 char nameBuff[20] = { 0 };
1002 const char* name = nameBuff;
1003 size_t const benchedSize = adv->blockSize ? adv->blockSize : 10000000;
Yann Collet2e45bad2018-08-23 14:21:18 -07001004
1005 /* Memory allocation */
Yann Collet0079d512024-10-22 02:18:48 -07001006 void* const srcBuffer = malloc(benchedSize);
Yann Colletdb792192023-03-06 12:15:22 -08001007 if (!srcBuffer) {
Yann Collet0079d512024-10-22 02:18:48 -07001008 DISPLAYLEVEL(1, "allocation error : not enough memory \n");
Yann Colletdb792192023-03-06 12:15:22 -08001009 return 16;
1010 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001011
1012 /* Fill input buffer */
Yann Colletd0b7da32024-01-29 15:00:32 -08001013 if (compressibility < 0.0) {
1014 LOREM_genBuffer(srcBuffer, benchedSize, 0);
1015 name = "Lorem ipsum";
1016 } else {
1017 RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);
Yann Collet588dfbc2024-02-20 19:21:01 -08001018 formatString_u(
Yann Collet7a225c02024-02-20 15:47:09 -08001019 nameBuff,
1020 sizeof(nameBuff),
Yann Collet588dfbc2024-02-20 19:21:01 -08001021 "Synthetic %u%%",
Yann Collet7a225c02024-02-20 15:47:09 -08001022 (unsigned)(compressibility * 100));
Yann Colletd0b7da32024-01-29 15:00:32 -08001023 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001024
1025 /* Bench */
Yann Collet0079d512024-10-22 02:18:48 -07001026 { int res = BMK_benchCLevels(
1027 srcBuffer,
1028 benchedSize,
1029 &benchedSize,
1030 1,
1031 startingCLevel, endCLevel,
1032 compressionParams,
1033 NULL,
1034 0, /* dictionary */
1035 displayLevel,
1036 name,
1037 adv);
1038 free(srcBuffer);
1039 return res;
1040 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001041}
1042
Yann Collet4856a002015-01-24 01:58:16 +01001043static size_t BMK_findMaxMem(U64 requiredMem)
1044{
Yann Colletde406ee2016-03-20 15:46:10 +01001045 size_t const step = 64 MB;
Yann Collet7a225c02024-02-20 15:47:09 -08001046 BYTE* testmem = NULL;
Yann Collet4856a002015-01-24 01:58:16 +01001047
1048 requiredMem = (((requiredMem >> 26) + 1) << 26);
Yann Colletde406ee2016-03-20 15:46:10 +01001049 requiredMem += step;
Yann Collet7a225c02024-02-20 15:47:09 -08001050 if (requiredMem > maxMemory)
1051 requiredMem = maxMemory;
Yann Collet4856a002015-01-24 01:58:16 +01001052
Yann Colletde406ee2016-03-20 15:46:10 +01001053 do {
Yann Collet4856a002015-01-24 01:58:16 +01001054 testmem = (BYTE*)malloc((size_t)requiredMem);
Yann Colletde406ee2016-03-20 15:46:10 +01001055 requiredMem -= step;
George Lue89f1fb2018-08-14 14:44:47 -07001056 } while (!testmem && requiredMem > 0);
Yann Colletde406ee2016-03-20 15:46:10 +01001057
Yann Collet4856a002015-01-24 01:58:16 +01001058 free(testmem);
Yann Colletde406ee2016-03-20 15:46:10 +01001059 return (size_t)(requiredMem);
Yann Collet4856a002015-01-24 01:58:16 +01001060}
1061
Yann Colleta5b66e32016-03-26 01:48:27 +01001062/*! BMK_loadFiles() :
Yann Collet6a9b41b2018-03-11 19:56:48 -07001063 * Loads `buffer` with content of files listed within `fileNamesTable`.
1064 * At most, fills `buffer` entirely. */
Yann Collet7a225c02024-02-20 15:47:09 -08001065static int BMK_loadFiles(
1066 void* buffer,
1067 size_t bufferSize,
1068 size_t* fileSizes,
1069 const char* const* fileNamesTable,
1070 unsigned nbFiles,
1071 int displayLevel)
Yann Colleted699e62015-12-16 02:37:24 +01001072{
inikepc0d5f4e2016-04-13 10:48:04 +02001073 size_t pos = 0, totalSize = 0;
Yann Collet699b14d2016-03-17 19:37:33 +01001074 unsigned n;
Yann Collet7a225c02024-02-20 15:47:09 -08001075 for (n = 0; n < nbFiles; n++) {
Yann Collet8edd1472024-10-01 09:52:45 -07001076 const char* const filename = fileNamesTable[n];
Yann Collet7a225c02024-02-20 15:47:09 -08001077 U64 fileSize = UTIL_getFileSize(
Yann Collet8edd1472024-10-01 09:52:45 -07001078 filename); /* last file may be shortened */
1079 if (UTIL_isDirectory(filename)) {
Yann Collet7a225c02024-02-20 15:47:09 -08001080 DISPLAYLEVEL(
Yann Collet8edd1472024-10-01 09:52:45 -07001081 2, "Ignoring %s directory... \n", filename);
inikepbab43172016-04-29 15:19:40 +02001082 fileSizes[n] = 0;
inikepc0d5f4e2016-04-13 10:48:04 +02001083 continue;
1084 }
Yann Collet18b79532017-10-17 16:14:25 -07001085 if (fileSize == UTIL_FILESIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -08001086 DISPLAYLEVEL(
1087 2,
1088 "Cannot evaluate size of %s, ignoring ... \n",
Yann Collet8edd1472024-10-01 09:52:45 -07001089 filename);
Yann Collet18b79532017-10-17 16:14:25 -07001090 fileSizes[n] = 0;
1091 continue;
1092 }
Yann Collet8edd1472024-10-01 09:52:45 -07001093 if (fileSize > bufferSize - pos) {
1094 /* buffer too small - limit quantity loaded */
1095 fileSize = bufferSize - pos;
1096 nbFiles = n; /* stop after this file */
1097 }
1098
1099 { FILE* const f = fopen(filename, "rb");
1100 if (f == NULL) {
Yann Collet7a225c02024-02-20 15:47:09 -08001101 RETURN_ERROR_INT(
Yann Collet8edd1472024-10-01 09:52:45 -07001102 10, "cannot open file %s", filename);
1103 }
1104 OUTPUTLEVEL(2, "Loading %s... \r", filename);
1105 { size_t const readSize =
Yann Collet7a225c02024-02-20 15:47:09 -08001106 fread(((char*)buffer) + pos, 1, (size_t)fileSize, f);
Yann Collet8edd1472024-10-01 09:52:45 -07001107 if (readSize != (size_t)fileSize) {
1108 fclose(f);
Yann Collet7a225c02024-02-20 15:47:09 -08001109 RETURN_ERROR_INT(
Yann Collet8edd1472024-10-01 09:52:45 -07001110 11, "invalid read %s", filename);
1111 }
Yann Collet6309be62019-10-15 16:09:18 -07001112 pos += readSize;
1113 }
1114 fileSizes[n] = (size_t)fileSize;
1115 totalSize += (size_t)fileSize;
1116 fclose(f);
Yann Collet7a225c02024-02-20 15:47:09 -08001117 }
1118 }
Yann Collet6f9c0562016-05-01 10:26:30 +02001119
Yann Collet7a225c02024-02-20 15:47:09 -08001120 if (totalSize == 0)
1121 RETURN_ERROR_INT(12, "no data to bench");
George Lu20f4f322018-06-12 15:54:43 -04001122 return 0;
Yann Colleted699e62015-12-16 02:37:24 +01001123}
1124
Yann Collet1e38e072023-03-06 12:34:13 -08001125int BMK_benchFilesAdvanced(
Yann Collet7a225c02024-02-20 15:47:09 -08001126 const char* const* fileNamesTable,
1127 unsigned nbFiles,
1128 const char* dictFileName,
Yann Collet0079d512024-10-22 02:18:48 -07001129 int startCLevel, int endCLevel,
Yann Collet7a225c02024-02-20 15:47:09 -08001130 const ZSTD_compressionParameters* compressionParams,
1131 int displayLevel,
1132 const BMK_advancedParams_t* adv)
Yann Colleted699e62015-12-16 02:37:24 +01001133{
George Lud6121ad2018-06-22 17:25:16 -07001134 void* srcBuffer = NULL;
Yann Colleted699e62015-12-16 02:37:24 +01001135 size_t benchedSize;
Yann Collet7a225c02024-02-20 15:47:09 -08001136 void* dictBuffer = NULL;
Yann Collet31683c02015-12-18 01:26:48 +01001137 size_t dictBufferSize = 0;
Yann Collet7a225c02024-02-20 15:47:09 -08001138 size_t* fileSizes = NULL;
Yann Collet0079d512024-10-22 02:18:48 -07001139 int res = 1;
Yann Collete162ace2016-05-20 11:24:35 +02001140 U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
Yann Colleted699e62015-12-16 02:37:24 +01001141
Yann Collet2e45bad2018-08-23 14:21:18 -07001142 if (!nbFiles) {
Yann Collet1e38e072023-03-06 12:34:13 -08001143 DISPLAYLEVEL(1, "No Files to Benchmark");
1144 return 13;
George Lua8eea992018-06-19 10:58:22 -07001145 }
Yann Collet31683c02015-12-18 01:26:48 +01001146
Yann Collet0079d512024-10-22 02:18:48 -07001147 if (endCLevel > ZSTD_maxCLevel()) {
Yann Collet1e38e072023-03-06 12:34:13 -08001148 DISPLAYLEVEL(1, "Invalid Compression Level");
1149 return 14;
George Lua8eea992018-06-19 10:58:22 -07001150 }
1151
senhuang42dce48f52021-08-23 19:10:16 -04001152 if (totalSizeToLoad == UTIL_FILESIZE_UNKNOWN) {
Yann Collet1e38e072023-03-06 12:34:13 -08001153 DISPLAYLEVEL(1, "Error loading files");
1154 return 15;
senhuang42dce48f52021-08-23 19:10:16 -04001155 }
1156
George Lua8eea992018-06-19 10:58:22 -07001157 fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t));
Yann Collet1e38e072023-03-06 12:34:13 -08001158 if (!fileSizes) {
1159 DISPLAYLEVEL(1, "not enough memory for fileSizes");
1160 return 16;
1161 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001162
Yann Collet31683c02015-12-18 01:26:48 +01001163 /* Load dictionary */
Yann Colletfd416f12016-01-30 03:14:15 +01001164 if (dictFileName != NULL) {
Yann Collet18b79532017-10-17 16:14:25 -07001165 U64 const dictFileSize = UTIL_getFileSize(dictFileName);
Yann Colleted2fb6b2018-12-20 17:20:07 -08001166 if (dictFileSize == UTIL_FILESIZE_UNKNOWN) {
Yann Collet7a225c02024-02-20 15:47:09 -08001167 DISPLAYLEVEL(
1168 1,
1169 "error loading %s : %s \n",
1170 dictFileName,
1171 strerror(errno));
Yann Colleted2fb6b2018-12-20 17:20:07 -08001172 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001173 DISPLAYLEVEL(1, "benchmark aborted");
1174 return 17;
Yann Colleted2fb6b2018-12-20 17:20:07 -08001175 }
George Lua8eea992018-06-19 10:58:22 -07001176 if (dictFileSize > 64 MB) {
1177 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001178 DISPLAYLEVEL(1, "dictionary file %s too large", dictFileName);
1179 return 18;
George Lua8eea992018-06-19 10:58:22 -07001180 }
Yann Collet31683c02015-12-18 01:26:48 +01001181 dictBufferSize = (size_t)dictFileSize;
Yann Collet7a225c02024-02-20 15:47:09 -08001182 dictBuffer = malloc(dictBufferSize);
1183 if (dictBuffer == NULL) {
George Lua8eea992018-06-19 10:58:22 -07001184 free(fileSizes);
Yann Collet7a225c02024-02-20 15:47:09 -08001185 DISPLAYLEVEL(
1186 1,
1187 "not enough memory for dictionary (%u bytes)",
1188 (unsigned)dictBufferSize);
Yann Collet1e38e072023-03-06 12:34:13 -08001189 return 19;
George Lua8eea992018-06-19 10:58:22 -07001190 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001191
Yann Collet7a225c02024-02-20 15:47:09 -08001192 {
1193 int const errorCode = BMK_loadFiles(
1194 dictBuffer,
1195 dictBufferSize,
1196 fileSizes,
1197 &dictFileName /*?*/,
1198 1 /*?*/,
1199 displayLevel);
Yann Collet2e45bad2018-08-23 14:21:18 -07001200 if (errorCode) {
George Lud6121ad2018-06-22 17:25:16 -07001201 goto _cleanUp;
Yann Collet7a225c02024-02-20 15:47:09 -08001202 }
1203 }
Yann Collet31683c02015-12-18 01:26:48 +01001204 }
1205
Yann Colleted699e62015-12-16 02:37:24 +01001206 /* Memory allocation & restrictions */
1207 benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;
Yann Collet7a225c02024-02-20 15:47:09 -08001208 if ((U64)benchedSize > totalSizeToLoad)
1209 benchedSize = (size_t)totalSizeToLoad;
Yann Colleted699e62015-12-16 02:37:24 +01001210 if (benchedSize < totalSizeToLoad)
Yann Collet7a225c02024-02-20 15:47:09 -08001211 DISPLAY("Not enough memory; testing %u MB only...\n",
1212 (unsigned)(benchedSize >> 20));
George Lue89f1fb2018-08-14 14:44:47 -07001213
1214 srcBuffer = benchedSize ? malloc(benchedSize) : NULL;
George Lua8eea992018-06-19 10:58:22 -07001215 if (!srcBuffer) {
1216 free(dictBuffer);
1217 free(fileSizes);
Yann Collet1e38e072023-03-06 12:34:13 -08001218 DISPLAYLEVEL(1, "not enough memory for srcBuffer");
1219 return 20;
George Lua8eea992018-06-19 10:58:22 -07001220 }
Yann Colleted699e62015-12-16 02:37:24 +01001221
1222 /* Load input buffer */
Yann Collet7a225c02024-02-20 15:47:09 -08001223 {
1224 int const errorCode = BMK_loadFiles(
1225 srcBuffer,
1226 benchedSize,
1227 fileSizes,
1228 fileNamesTable,
1229 nbFiles,
1230 displayLevel);
Yann Collet2e45bad2018-08-23 14:21:18 -07001231 if (errorCode) {
George Lud6121ad2018-06-22 17:25:16 -07001232 goto _cleanUp;
Yann Collet7a225c02024-02-20 15:47:09 -08001233 }
1234 }
Yann Collet2e45bad2018-08-23 14:21:18 -07001235
Yann Colleted699e62015-12-16 02:37:24 +01001236 /* Bench */
Yann Collet7a225c02024-02-20 15:47:09 -08001237 {
1238 char mfName[20] = { 0 };
Yann Collet588dfbc2024-02-20 19:21:01 -08001239 formatString_u(mfName, sizeof(mfName), " %u files", nbFiles);
Yann Collet0079d512024-10-22 02:18:48 -07001240 { const char* const displayName =
Yann Collet7a225c02024-02-20 15:47:09 -08001241 (nbFiles > 1) ? mfName : fileNamesTable[0];
Yann Collet0079d512024-10-22 02:18:48 -07001242 res = BMK_benchCLevels(
Yann Collet7a225c02024-02-20 15:47:09 -08001243 srcBuffer,
1244 benchedSize,
1245 fileSizes,
1246 nbFiles,
Yann Collet0079d512024-10-22 02:18:48 -07001247 startCLevel, endCLevel,
Yann Collet7a225c02024-02-20 15:47:09 -08001248 compressionParams,
1249 dictBuffer,
1250 dictBufferSize,
1251 displayLevel,
1252 displayName,
1253 adv);
1254 }
1255 }
Yann Collet4856a002015-01-24 01:58:16 +01001256
George Lud6121ad2018-06-22 17:25:16 -07001257_cleanUp:
Yann Collet4856a002015-01-24 01:58:16 +01001258 free(srcBuffer);
Yann Collet31683c02015-12-18 01:26:48 +01001259 free(dictBuffer);
Yann Collet70611352015-12-16 03:01:03 +01001260 free(fileSizes);
Yann Collet0079d512024-10-22 02:18:48 -07001261 return res;
Yann Collet4856a002015-01-24 01:58:16 +01001262}
1263
Yann Collet7a225c02024-02-20 15:47:09 -08001264int BMK_benchFiles(
1265 const char* const* fileNamesTable,
1266 unsigned nbFiles,
1267 const char* dictFileName,
1268 int cLevel,
1269 const ZSTD_compressionParameters* compressionParams,
1270 int displayLevel)
Yann Collet4856a002015-01-24 01:58:16 +01001271{
Yann Collet2e45bad2018-08-23 14:21:18 -07001272 BMK_advancedParams_t const adv = BMK_initAdvancedParams();
Yann Collet7a225c02024-02-20 15:47:09 -08001273 return BMK_benchFilesAdvanced(
1274 fileNamesTable,
1275 nbFiles,
1276 dictFileName,
Yann Collet0079d512024-10-22 02:18:48 -07001277 cLevel, cLevel,
Yann Collet7a225c02024-02-20 15:47:09 -08001278 compressionParams,
1279 displayLevel,
1280 &adv);
Yann Collet4856a002015-01-24 01:58:16 +01001281}