refactored bench.c

for clarity and safety, especially at interface level
This commit is contained in:
Yann Collet 2018-08-23 14:21:18 -07:00
parent 77e805e3db
commit 2e45badff4
3 changed files with 587 additions and 475 deletions

View File

@ -1322,8 +1322,7 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
} }
/* copy dictionary offsets */ /* copy dictionary offsets */
{ { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
dstMatchState->window = srcMatchState->window; dstMatchState->window = srcMatchState->window;
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;

File diff suppressed because it is too large Load Diff

View File

@ -26,19 +26,32 @@ extern "C" {
* will either be successful, with .error = 0, providing a valid .result, * will either be successful, with .error = 0, providing a valid .result,
* or return an error, with .error != 0, in which case .result is invalid. * or return an error, with .error != 0, in which case .result is invalid.
*/ */
#define ERROR_STRUCT(baseType, typeName) typedef struct { \ #define SUMTYPE_ERROR_RESULT(baseType, variantName) \
baseType result; \ \
int error; \ typedef struct { \
} typeName baseType internal_never_use_directly; \
int tag; \
} variantName
typedef struct { typedef struct {
size_t cSize; size_t cSize;
unsigned long long cSpeed; /* bytes / sec */ unsigned long long cSpeed; /* bytes / sec */
unsigned long long dSpeed; unsigned long long dSpeed;
size_t cMem; /* ? what does it reports ? */ size_t cMem; /* ? what is reported ? */
} BMK_result_t; } BMK_benchResult_t;
SUMTYPE_ERROR_RESULT(BMK_benchResult_t, BMK_benchOutcome_t);
/* check first if the return structure represents an error or a valid result */
int BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t errorOrResult);
/* extract result from variant type.
* note : this function will abort() program execution if result is not valid
* check result validity first, by using BMK_isValid_benchResult()
*/
BMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t errorOrResult);
ERROR_STRUCT(BMK_result_t, BMK_return_t);
/*! BMK_benchFiles() -- called by zstdcli */ /*! BMK_benchFiles() -- called by zstdcli */
/* Loads files from fileNamesTable into memory, /* Loads files from fileNamesTable into memory,
@ -61,15 +74,12 @@ ERROR_STRUCT(BMK_result_t, BMK_return_t);
* .result will return compression speed (.cSpeed), * .result will return compression speed (.cSpeed),
* decompression speed (.dSpeed), and compressed size (.cSize). * decompression speed (.dSpeed), and compressed size (.cSize).
*/ */
BMK_return_t BMK_benchFiles(const char* const * fileNamesTable, unsigned nbFiles, BMK_benchOutcome_t BMK_benchFiles(
const char* const * fileNamesTable, unsigned nbFiles,
const char* dictFileName, const char* dictFileName,
int cLevel, const ZSTD_compressionParameters* compressionParams, int cLevel, const ZSTD_compressionParameters* compressionParams,
int displayLevel); int displayLevel);
typedef enum {
BMK_timeMode = 0,
BMK_iterMode = 1
} BMK_loopMode_t;
typedef enum { typedef enum {
BMK_both = 0, BMK_both = 0,
@ -79,7 +89,6 @@ typedef enum {
typedef struct { typedef struct {
BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */ BMK_mode_t mode; /* 0: all, 1: compress only 2: decode only */
BMK_loopMode_t loopMode; /* if loopmode, then nbSeconds = nbLoops */
unsigned nbSeconds; /* default timing is in nbSeconds */ unsigned nbSeconds; /* default timing is in nbSeconds */
size_t blockSize; /* Maximum allowable size of a block*/ size_t blockSize; /* Maximum allowable size of a block*/
unsigned nbWorkers; /* multithreading */ unsigned nbWorkers; /* multithreading */
@ -98,7 +107,8 @@ BMK_advancedParams_t BMK_initAdvancedParams(void);
/*! BMK_benchFilesAdvanced(): /*! BMK_benchFilesAdvanced():
* Same as BMK_benchFiles(), * Same as BMK_benchFiles(),
* with more controls, provided through advancedParams_t structure */ * with more controls, provided through advancedParams_t structure */
BMK_return_t BMK_benchFilesAdvanced(const char* const * fileNamesTable, unsigned nbFiles, BMK_benchOutcome_t BMK_benchFilesAdvanced(
const char* const * fileNamesTable, unsigned nbFiles,
const char* dictFileName, const char* dictFileName,
int cLevel, const ZSTD_compressionParameters* compressionParams, int cLevel, const ZSTD_compressionParameters* compressionParams,
int displayLevel, const BMK_advancedParams_t* adv); int displayLevel, const BMK_advancedParams_t* adv);
@ -116,10 +126,15 @@ BMK_return_t BMK_benchFilesAdvanced(const char* const * fileNamesTable, unsigned
* .result will return the compression speed (.cSpeed), * .result will return the compression speed (.cSpeed),
* decompression speed (.dSpeed), and compressed size (.cSize). * decompression speed (.dSpeed), and compressed size (.cSize).
*/ */
BMK_return_t BMK_syntheticTest(int cLevel, double compressibility, BMK_benchOutcome_t BMK_syntheticTest(
int cLevel, double compressibility,
const ZSTD_compressionParameters* compressionParams, const ZSTD_compressionParameters* compressionParams,
int displayLevel, const BMK_advancedParams_t * const adv); int displayLevel, const BMK_advancedParams_t * const adv);
/* === Benchmark Zstandard in a memory-to-memory scenario === */
/** BMK_benchMem() -- core benchmarking function, called in paramgrill /** BMK_benchMem() -- core benchmarking function, called in paramgrill
* applies ZSTD_compress_generic() and ZSTD_decompress_generic() on data in srcBuffer * applies ZSTD_compress_generic() and ZSTD_decompress_generic() on data in srcBuffer
* with specific compression parameters provided by other arguments using benchFunction * with specific compression parameters provided by other arguments using benchFunction
@ -141,7 +156,7 @@ BMK_return_t BMK_syntheticTest(int cLevel, double compressibility,
* provide the same results as benchFiles() * provide the same results as benchFiles()
* but for the data stored in srcBuffer * but for the data stored in srcBuffer
*/ */
BMK_return_t BMK_benchMem(const void* srcBuffer, size_t srcSize, BMK_benchOutcome_t BMK_benchMem(const void* srcBuffer, size_t srcSize,
const size_t* fileSizes, unsigned nbFiles, const size_t* fileSizes, unsigned nbFiles,
int cLevel, const ZSTD_compressionParameters* comprParams, int cLevel, const ZSTD_compressionParameters* comprParams,
const void* dictBuffer, size_t dictBufferSize, const void* dictBuffer, size_t dictBufferSize,
@ -153,7 +168,7 @@ BMK_return_t BMK_benchMem(const void* srcBuffer, size_t srcSize,
* dstCapacity - capacity of destination buffer, give 0 if dstBuffer = NULL * dstCapacity - capacity of destination buffer, give 0 if dstBuffer = NULL
* adv = see advancedParams_t * adv = see advancedParams_t
*/ */
BMK_return_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize, BMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,
void* dstBuffer, size_t dstCapacity, void* dstBuffer, size_t dstCapacity,
const size_t* fileSizes, unsigned nbFiles, const size_t* fileSizes, unsigned nbFiles,
int cLevel, const ZSTD_compressionParameters* comprParams, int cLevel, const ZSTD_compressionParameters* comprParams,
@ -161,74 +176,107 @@ BMK_return_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,
int displayLevel, const char* displayName, int displayLevel, const char* displayName,
const BMK_advancedParams_t* adv); const BMK_advancedParams_t* adv);
/* ==== Benchmarking any function, iterated on a set of blocks ==== */
typedef struct { typedef struct {
size_t sumOfReturn; /* sum of return values */ unsigned long long nanoSecPerRun; /* time per iteration */
unsigned long long nanoSecPerRun; /* time per iteration */ size_t sumOfReturn; /* sum of return values */
} BMK_customResult_t; } BMK_runTime_t;
ERROR_STRUCT(BMK_customResult_t, BMK_customReturn_t); SUMTYPE_ERROR_RESULT(BMK_runTime_t, BMK_runOutcome_t);
typedef size_t (*BMK_benchFn_t)(const void*, size_t, void*, size_t, void*); /* check first if the return structure represents an error or a valid result */
typedef size_t (*BMK_initFn_t)(void*); int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome);
/* This function times the execution of 2 argument functions, benchFn and initFn */ /* extract result from variant type.
* note : this function will abort() program execution if result is not valid
* check result validity first, by using BMK_isSuccessful_runOutcome()
*/
BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome);
typedef size_t (*BMK_benchFn_t)(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload);
typedef size_t (*BMK_initFn_t)(void* initPayload);
/* BMK_benchFunction() :
* This function times the execution of 2 argument functions, benchFn and initFn */
/* benchFn - (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) /* benchFn - (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload)
* is run nbLoops times * is run nbLoops times
* initFn - (*initFn)(initPayload) is run once per benchmark at the beginning. This argument can * initFn - (*initFn)(initPayload) is run once per benchmark, at the beginning.
* be NULL, in which case nothing is run. * This argument can be NULL, in which case nothing is run.
* blockCount - number of blocks. Size of all array parameters : srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults * blockCount - number of blocks. Size of all array parameters : srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults
* srcBuffers - an array of buffers to be operated on by benchFn * srcBuffers - an array of buffers to be operated on by benchFn
* srcSizes - an array of the sizes of above buffers * srcSizes - an array of the sizes of above buffers
* dstBuffers - an array of buffers to be written into by benchFn * dstBuffers - an array of buffers to be written into by benchFn
* dstCapacities - an array of the capacities of above buffers * dstCapacities - an array of the capacities of above buffers
* blockResults - the return value of benchFn called on each block. * blockResults - store the return value of benchFn for each block. Optional. Use NULL if this result is not requested.
* nbLoops - defines number of times benchFn is run. * nbLoops - defines number of times benchFn is run.
* @return: * @return: a variant, which can be an error, or a BMK_runTime_t result.
* .error will give a nonzero value if ZSTD_isError() is nonzero for any of the return * Use BMK_isSuccessful_runOutcome() to check if function was successful.
* of the calls to initFn and benchFn, or if benchFunction errors internally * If yes, extract the result with BMK_extract_runTime(),
* .result - if .error = 0, then .result will contain * it will contain :
* the sum of all return values of benchFn on the first iteration through all of the blocks (.sumOfReturn) * .sumOfReturn : the sum of all return values of benchFn through all of blocks
* and also the time per run of benchFn (.nanoSecPerRun). * .nanoSecPerRun : time per run of benchFn + (time for initFn / nbLoops)
* For the former, this is generally intended to be used on functions which return the # of bytes written into dstBuffer, * .sumOfReturn is generally intended for functions which return a # of bytes written into dstBuffer,
* hence this value will be the total amount of bytes written into dstBuffer. * in which case, this value will be the total amount of bytes written into dstBuffer.
*/ */
BMK_customReturn_t BMK_benchFunction(BMK_benchFn_t benchFn, void* benchPayload, BMK_runOutcome_t BMK_benchFunction(
BMK_benchFn_t benchFn, void* benchPayload,
BMK_initFn_t initFn, void* initPayload, BMK_initFn_t initFn, void* initPayload,
size_t blockCount, size_t blockCount,
const void *const * srcBuffers, const size_t* srcSizes, const void *const * srcBuffers, const size_t* srcSizes,
void *const * dstBuffers, const size_t* dstCapacities, size_t* blockResults, void *const * dstBuffers, const size_t* dstCapacities,
size_t* blockResults,
unsigned nbLoops); unsigned nbLoops);
/* state information needed to advance computation for benchFunctionTimed */
typedef struct BMK_timeState_t BMK_timedFnState_t; /* ==== Benchmarking any function, providing intermediate results ==== */
/* initializes timeState object with desired number of seconds */
/* state information needed by benchFunctionTimed */
typedef struct BMK_timedFnState_s BMK_timedFnState_t;
BMK_timedFnState_t* BMK_createTimedFnState(unsigned nbSeconds); BMK_timedFnState_t* BMK_createTimedFnState(unsigned nbSeconds);
/* resets existing timeState object */ void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned nbSeconds);
void BMK_resetTimedFnState(BMK_timedFnState_t*, unsigned nbSeconds);
/* deletes timeState object */
void BMK_freeTimedFnState(BMK_timedFnState_t* state); void BMK_freeTimedFnState(BMK_timedFnState_t* state);
typedef struct { /* define timedFnOutcome */
BMK_customReturn_t result; SUMTYPE_ERROR_RESULT(BMK_runTime_t, BMK_timedFnOutcome_t);
int completed;
} BMK_customTimedReturn_t; /* check first if the return structure represents an error or a valid result */
int BMK_isSuccessful_timedFnOutcome(BMK_timedFnOutcome_t outcome);
/* extract intermediate results from variant type.
* note : this function will abort() program execution if result is not valid.
* check result validity first, by using BMK_isSuccessful_timedFnOutcome() */
BMK_runTime_t BMK_extract_timedFnResult(BMK_timedFnOutcome_t outcome);
/* Tells if nb of seconds set in timedFnState for all runs is spent.
* note : this function will return 1 if BMK_benchFunctionTimed() has actually errored. */
int BMK_isCompleted_timedFnOutcome(BMK_timedFnOutcome_t outcome);
/* BMK_benchFunctionTimed() : /* BMK_benchFunctionTimed() :
* Same as BMK_benchFunction(), but runs for nbSeconds seconds rather than a fixed number of loops. * Similar to BMK_benchFunction(),
* Arguments are mostly the same other as BMK_benchFunction() * tries to find automatically `nbLoops`, so that each run lasts approximately 1 second.
* Usage - benchFunctionTimed will return in approximately one second. * Note : minimum `nbLoops` is 1, a run may last more than 1 second if benchFn is slow.
* Keep calling BMK_benchFunctionTimed() until @return.completed == 1, * Most arguments are the same as BMK_benchFunction()
* to continue updating intermediate result. * Usage - initialize a timedFnState, selecting a total nbSeconds allocated for _all_ benchmarks run
* Intermediate return values are returned by the function. * call BMK_benchFunctionTimed() repetitively, collecting intermediate results (each run is supposed to last about 1 seconds)
* Check if time budget is spent using BMK_isCompleted_timedFnOutcome()
*/ */
BMK_customTimedReturn_t BMK_benchFunctionTimed(BMK_timedFnState_t* cont, BMK_timedFnOutcome_t BMK_benchFunctionTimed(
BMK_benchFn_t benchFn, void* benchPayload, BMK_timedFnState_t* timedFnState,
BMK_initFn_t initFn, void* initPayload, BMK_benchFn_t benchFn, void* benchPayload,
size_t blockCount, BMK_initFn_t initFn, void* initPayload,
const void *const * srcBlockBuffers, const size_t* srcBlockSizes, size_t blockCount,
void *const * dstBlockBuffers, const size_t* dstBlockCapacities, size_t* blockResults); const void *const * srcBlockBuffers, const size_t* srcBlockSizes,
void *const * dstBlockBuffers, const size_t* dstBlockCapacities,
size_t* blockResults);
#endif /* BENCH_H_121279284357 */ #endif /* BENCH_H_121279284357 */