2 * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
5 * 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).
8 * You may select, at your option, one of the above-listed licenses.
11 #if defined (__cplusplus)
15 #ifndef BENCH_H_121279284357
16 #define BENCH_H_121279284357
18 /* === Dependencies === */
19 #include <stddef.h> /* size_t */
20 #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */
21 #include "zstd.h" /* ZSTD_compressionParameters */
24 /* === Constants === */
26 #define MB_UNIT 1000000
29 /* === Benchmark functions === */
31 /* Creates a variant `typeName`, able to express "error or valid result".
32 * Functions with return type `typeName`
33 * must first check if result is valid, using BMK_isSuccessful_*(),
34 * and only then can extract `baseType`.
36 #define VARIANT_ERROR_RESULT(baseType, variantName) \
39 baseType internal_never_use_directly; \
46 unsigned long long cSpeed; /* bytes / sec */
47 unsigned long long dSpeed;
48 size_t cMem; /* memory usage during compression */
51 VARIANT_ERROR_RESULT(BMK_benchResult_t, BMK_benchOutcome_t);
53 /* check first if the return structure represents an error or a valid result */
54 int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome);
56 /* extract result from variant type.
57 * note : this function will abort() program execution if result is not valid
58 * check result validity first, by using BMK_isSuccessful_benchOutcome()
60 BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome);
63 /*! BMK_benchFiles() -- called by zstdcli */
64 /* Loads files from fileNamesTable into memory,
65 * and an optional dictionary from dictFileName (can be NULL),
66 * then uses benchMem().
67 * fileNamesTable - name of files to benchmark.
68 * nbFiles - number of files (size of fileNamesTable), must be > 0.
69 * dictFileName - name of dictionary file to load.
70 * cLevel - compression level to benchmark, errors if invalid.
71 * compressionParams - advanced compression Parameters.
72 * displayLevel - what gets printed:
75 * 2 : + result + interaction + warnings;
79 * a variant, which expresses either an error, or a valid result.
80 * Use BMK_isSuccessful_benchOutcome() to check if function was successful.
81 * If yes, extract the valid result with BMK_extract_benchResult(),
83 * .cSpeed: compression speed in bytes per second,
84 * .dSpeed: decompression speed in bytes per second,
85 * .cSize : compressed size, in bytes
86 * .cMem : memory budget required for the compression context
88 BMK_benchOutcome_t BMK_benchFiles(
89 const char* const * fileNamesTable, unsigned nbFiles,
90 const char* dictFileName,
91 int cLevel, const ZSTD_compressionParameters* compressionParams,
102 BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
103 unsigned nbSeconds; /* default timing is in nbSeconds */
104 size_t blockSize; /* Maximum size of each block*/
105 unsigned nbWorkers; /* multithreading */
106 unsigned realTime; /* real time priority */
107 int additionalParam; /* used by python speed benchmark */
108 unsigned ldmFlag; /* enables long distance matching */
109 unsigned ldmMinMatch; /* below: parameters for long distance matching, see zstd.1.md */
111 unsigned ldmBucketSizeLog;
112 unsigned ldmHashEveryLog;
113 } BMK_advancedParams_t;
115 /* returns default parameters used by nonAdvanced functions */
116 BMK_advancedParams_t BMK_initAdvancedParams(void);
118 /*! BMK_benchFilesAdvanced():
119 * Same as BMK_benchFiles(),
120 * with more controls, provided through advancedParams_t structure */
121 BMK_benchOutcome_t BMK_benchFilesAdvanced(
122 const char* const * fileNamesTable, unsigned nbFiles,
123 const char* dictFileName,
124 int cLevel, const ZSTD_compressionParameters* compressionParams,
125 int displayLevel, const BMK_advancedParams_t* adv);
127 /*! BMK_syntheticTest() -- called from zstdcli */
128 /* Generates a sample with datagen, using compressibility argument */
129 /* cLevel - compression level to benchmark, errors if invalid
130 * compressibility - determines compressibility of sample
131 * compressionParams - basic compression Parameters
132 * displayLevel - see benchFiles
133 * adv - see advanced_Params_t
135 * a variant, which expresses either an error, or a valid result.
136 * Use BMK_isSuccessful_benchOutcome() to check if function was successful.
137 * If yes, extract the valid result with BMK_extract_benchResult(),
139 * .cSpeed: compression speed in bytes per second,
140 * .dSpeed: decompression speed in bytes per second,
141 * .cSize : compressed size, in bytes
142 * .cMem : memory budget required for the compression context
144 BMK_benchOutcome_t BMK_syntheticTest(
145 int cLevel, double compressibility,
146 const ZSTD_compressionParameters* compressionParams,
147 int displayLevel, const BMK_advancedParams_t* adv);
151 /* === Benchmark Zstandard in a memory-to-memory scenario === */
153 /** BMK_benchMem() -- core benchmarking function, called in paramgrill
154 * applies ZSTD_compress_generic() and ZSTD_decompress_generic() on data in srcBuffer
155 * with specific compression parameters provided by other arguments using benchFunction
156 * (cLevel, comprParams + adv in advanced Mode) */
157 /* srcBuffer - data source, expected to be valid compressed data if in Decode Only Mode
158 * srcSize - size of data in srcBuffer
159 * fileSizes - srcBuffer is considered cut into 1+ segments, to compress separately.
160 * note : sum(fileSizes) must be == srcSize. (<== ensure it's properly checked)
161 * nbFiles - nb of segments
162 * cLevel - compression level
163 * comprParams - basic compression parameters
164 * dictBuffer - a dictionary if used, null otherwise
165 * dictBufferSize - size of dictBuffer, 0 otherwise
166 * diplayLevel - see BMK_benchFiles
167 * displayName - name used by display
169 * a variant, which expresses either an error, or a valid result.
170 * Use BMK_isSuccessful_benchOutcome() to check if function was successful.
171 * If yes, extract the valid result with BMK_extract_benchResult(),
173 * .cSpeed: compression speed in bytes per second,
174 * .dSpeed: decompression speed in bytes per second,
175 * .cSize : compressed size, in bytes
176 * .cMem : memory budget required for the compression context
178 BMK_benchOutcome_t BMK_benchMem(const void* srcBuffer, size_t srcSize,
179 const size_t* fileSizes, unsigned nbFiles,
180 int cLevel, const ZSTD_compressionParameters* comprParams,
181 const void* dictBuffer, size_t dictBufferSize,
182 int displayLevel, const char* displayName);
184 /* BMK_benchMemAdvanced() : same as BMK_benchMem()
185 * with following additional options :
186 * dstBuffer - destination buffer to write compressed output in, NULL if none provided.
187 * dstCapacity - capacity of destination buffer, give 0 if dstBuffer = NULL
188 * adv = see advancedParams_t
190 BMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,
191 void* dstBuffer, size_t dstCapacity,
192 const size_t* fileSizes, unsigned nbFiles,
193 int cLevel, const ZSTD_compressionParameters* comprParams,
194 const void* dictBuffer, size_t dictBufferSize,
195 int displayLevel, const char* displayName,
196 const BMK_advancedParams_t* adv);
200 /* ==== Benchmarking any function, iterated on a set of blocks ==== */
203 unsigned long long nanoSecPerRun; /* time per iteration */
204 size_t sumOfReturn; /* sum of return values */
207 VARIANT_ERROR_RESULT(BMK_runTime_t, BMK_runOutcome_t);
209 /* check first if the return structure represents an error or a valid result */
210 int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome);
212 /* extract result from variant type.
213 * note : this function will abort() program execution if result is not valid
214 * check result validity first, by using BMK_isSuccessful_runOutcome()
216 BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome);
220 typedef size_t (*BMK_benchFn_t)(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload);
221 typedef size_t (*BMK_initFn_t)(void* initPayload);
224 /* BMK_benchFunction() :
225 * This function times the execution of 2 argument functions, benchFn and initFn */
227 /* benchFn - (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload)
228 * is run nbLoops times
229 * initFn - (*initFn)(initPayload) is run once per benchmark, at the beginning.
230 * This argument can be NULL, in which case nothing is run.
231 * blockCount - number of blocks. Size of all array parameters : srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults
232 * srcBuffers - an array of buffers to be operated on by benchFn
233 * srcSizes - an array of the sizes of above buffers
234 * dstBuffers - an array of buffers to be written into by benchFn
235 * dstCapacities - an array of the capacities of above buffers
236 * blockResults - Optional: store the return value of benchFn for each block. Use NULL if this result is not requested.
237 * nbLoops - defines number of times benchFn is run.
238 * @return: a variant, which express either an error, or can generate a valid BMK_runTime_t result.
239 * Use BMK_isSuccessful_runOutcome() to check if function was successful.
240 * If yes, extract the result with BMK_extract_runTime(),
242 * .sumOfReturn : the sum of all return values of benchFn through all of blocks
243 * .nanoSecPerRun : time per run of benchFn + (time for initFn / nbLoops)
244 * .sumOfReturn is generally intended for functions which return a # of bytes written into dstBuffer,
245 * in which case, this value will be the total amount of bytes written into dstBuffer.
247 BMK_runOutcome_t BMK_benchFunction(
248 BMK_benchFn_t benchFn, void* benchPayload,
249 BMK_initFn_t initFn, void* initPayload,
251 const void *const * srcBuffers, const size_t* srcSizes,
252 void *const * dstBuffers, const size_t* dstCapacities,
253 size_t* blockResults,
258 /* ==== Benchmark any function, providing intermediate results ==== */
260 /* state information tracking benchmark session */
261 typedef struct BMK_timedFnState_s BMK_timedFnState_t;
263 /* BMK_createTimedFnState() and BMK_resetTimedFnState() :
264 * Create/Set BMK_timedFnState_t for next benchmark session,
265 * which shall last a minimum of total_ms milliseconds,
266 * producing intermediate results, paced at interval of (approximately) run_ms.
268 BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms);
269 void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms);
270 void BMK_freeTimedFnState(BMK_timedFnState_t* state);
273 /* Tells if duration of all benchmark runs has exceeded total_ms
275 int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState);
278 /* BMK_benchTimedFn() :
279 * Similar to BMK_benchFunction(), most arguments being identical.
280 * Automatically determines `nbLoops` so that each result is regularly produced at interval of about run_ms.
281 * Note : minimum `nbLoops` is 1, therefore a run may last more than run_ms, and possibly even more than total_ms.
282 * Usage - initialize timedFnState, select benchmark duration (total_ms) and each measurement duration (run_ms)
283 * call BMK_benchTimedFn() repetitively, each measurement is supposed to last about run_ms
284 * Check if total time budget is spent or exceeded, using BMK_isCompleted_TimedFn()
286 BMK_runOutcome_t BMK_benchTimedFn(
287 BMK_timedFnState_t* timedFnState,
288 BMK_benchFn_t benchFn, void* benchPayload,
289 BMK_initFn_t initFn, void* initPayload,
291 const void *const * srcBlockBuffers, const size_t* srcBlockSizes,
292 void *const * dstBlockBuffers, const size_t* dstBlockCapacities,
293 size_t* blockResults);
299 #endif /* BENCH_H_121279284357 */
301 #if defined (__cplusplus)