Path: blob/main/sys/contrib/zstd/programs/benchfn.h
48254 views
/*1* Copyright (c) Yann Collet, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/91011/* benchfn :12* benchmark any function on a set of input13* providing result in nanoSecPerRun14* or detecting and returning an error15*/1617#if defined (__cplusplus)18extern "C" {19#endif2021#ifndef BENCH_FN_H_2387622#define BENCH_FN_H_238762324/* === Dependencies === */25#include <stddef.h> /* size_t */262728/* ==== Benchmark any function, iterated on a set of blocks ==== */2930/* BMK_runTime_t: valid result return type */3132typedef struct {33double nanoSecPerRun; /* time per iteration (over all blocks) */34size_t sumOfReturn; /* sum of return values */35} BMK_runTime_t;363738/* BMK_runOutcome_t:39* type expressing the outcome of a benchmark run by BMK_benchFunction(),40* which can be either valid or invalid.41* benchmark outcome can be invalid if errorFn is provided.42* BMK_runOutcome_t must be considered "opaque" : never access its members directly.43* Instead, use its assigned methods :44* BMK_isSuccessful_runOutcome, BMK_extract_runTime, BMK_extract_errorResult.45* The structure is only described here to allow its allocation on stack. */4647typedef struct {48BMK_runTime_t internal_never_ever_use_directly;49size_t error_result_never_ever_use_directly;50int error_tag_never_ever_use_directly;51} BMK_runOutcome_t;525354/* prototypes for benchmarked functions */55typedef size_t (*BMK_benchFn_t)(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload);56typedef size_t (*BMK_initFn_t)(void* initPayload);57typedef unsigned (*BMK_errorFn_t)(size_t);585960/* BMK_benchFunction() parameters are provided via the following structure.61* A structure is preferable for readability,62* as the number of parameters required is fairly large.63* No initializer is provided, because it doesn't make sense to provide some "default" :64* all parameters must be specified by the caller.65* optional parameters are labelled explicitly, and accept value NULL when not used */66typedef struct {67BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */68void* benchPayload; /* pass custom parameters to benchFn :69* (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */70BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */71void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */72BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not.73* errorFn can be NULL, in which case no check is performed.74* errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error.75* Execution is stopped as soon as an error is detected.76* the triggering return value can be retrieved using BMK_extract_errorResult(). */77size_t blockCount; /* number of blocks to operate benchFn on.78* It's also the size of all array parameters :79* srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */80const void *const * srcBuffers; /* read-only array of buffers to be operated on by benchFn */81const size_t* srcSizes; /* read-only array containing sizes of srcBuffers */82void *const * dstBuffers; /* array of buffers to be written into by benchFn. This array is not optional, it must be provided even if unused by benchfn. */83const size_t* dstCapacities; /* read-only array containing capacities of dstBuffers. This array must be present. */84size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */85} BMK_benchParams_t;868788/* BMK_benchFunction() :89* This function benchmarks benchFn and initFn, providing a result.90*91* params : see description of BMK_benchParams_t above.92* nbLoops: defines number of times benchFn is run over the full set of blocks.93* Minimum value is 1. A 0 is interpreted as a 1.94*95* @return: can express either an error or a successful result.96* Use BMK_isSuccessful_runOutcome() to check if benchmark was successful.97* If yes, extract the result with BMK_extract_runTime(),98* it will contain :99* .sumOfReturn : the sum of all return values of benchFn through all of blocks100* .nanoSecPerRun : time per run of benchFn + (time for initFn / nbLoops)101* .sumOfReturn is generally intended for functions which return a # of bytes written into dstBuffer,102* in which case, this value will be the total amount of bytes written into dstBuffer.103*104* blockResults : when provided (!= NULL), and when benchmark is successful,105* params.blockResults contains all return values of `benchFn` over all blocks.106* when provided (!= NULL), and when benchmark failed,107* params.blockResults contains return values of `benchFn` over all blocks preceding and including the failed block.108*/109BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t params, unsigned nbLoops);110111112113/* check first if the benchmark was successful or not */114int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome);115116/* If the benchmark was successful, extract the result.117* note : this function will abort() program execution if benchmark failed !118* always check if benchmark was successful first !119*/120BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome);121122/* when benchmark failed, it means one invocation of `benchFn` failed.123* The failure was detected by `errorFn`, operating on return values of `benchFn`.124* Returns the faulty return value.125* note : this function will abort() program execution if benchmark did not failed.126* always check if benchmark failed first !127*/128size_t BMK_extract_errorResult(BMK_runOutcome_t outcome);129130131132/* ==== Benchmark any function, returning intermediate results ==== */133134/* state information tracking benchmark session */135typedef struct BMK_timedFnState_s BMK_timedFnState_t;136137/* BMK_benchTimedFn() :138* Similar to BMK_benchFunction(), most arguments being identical.139* Automatically determines `nbLoops` so that each result is regularly produced at interval of about run_ms.140* Note : minimum `nbLoops` is 1, therefore a run may last more than run_ms, and possibly even more than total_ms.141* Usage - initialize timedFnState, select benchmark duration (total_ms) and each measurement duration (run_ms)142* call BMK_benchTimedFn() repetitively, each measurement is supposed to last about run_ms143* Check if total time budget is spent or exceeded, using BMK_isCompleted_TimedFn()144*/145BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* timedFnState,146BMK_benchParams_t params);147148/* Tells if duration of all benchmark runs has exceeded total_ms149*/150int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState);151152/* BMK_createTimedFnState() and BMK_resetTimedFnState() :153* Create/Set BMK_timedFnState_t for next benchmark session,154* which shall last a minimum of total_ms milliseconds,155* producing intermediate results, paced at interval of (approximately) run_ms.156*/157BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms);158void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms);159void BMK_freeTimedFnState(BMK_timedFnState_t* state);160161162/* BMK_timedFnState_shell and BMK_initStatic_timedFnState() :163* Makes it possible to statically allocate a BMK_timedFnState_t on stack.164* BMK_timedFnState_shell is only there to allocate space,165* never ever access its members.166* BMK_timedFnState_t() actually accepts any buffer.167* It will check if provided buffer is large enough and is correctly aligned,168* and will return NULL if conditions are not respected.169*/170#define BMK_TIMEDFNSTATE_SIZE 64171typedef union {172char never_access_space[BMK_TIMEDFNSTATE_SIZE];173long long alignment_enforcer; /* must be aligned on 8-bytes boundaries */174} BMK_timedFnState_shell;175BMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms);176177178#endif /* BENCH_FN_H_23876 */179180#if defined (__cplusplus)181}182#endif183184185