Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 386 additions & 0 deletions lib/node_modules/@stdlib/bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,390 @@ This function is an alias for [@stdlib/bench/harness][@stdlib/bench/harness].

<!-- /.examples -->

<!-- C interface documentation. -->

* * *

<section class="c">

## C APIs

<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->

<section class="intro">

The C harness is a header-only library of macros and `static inline` helpers which emit the same [Test Anything Protocol][tap] (TAP) output as hand-written stdlib C benchmarks, so that a benchmark file contains only the code being measured.

</section>

<!-- /.intro -->

<!-- C usage documentation. -->

<section class="usage">

### Usage

```c
#include "stdlib/bench.h"
```

#### BENCHMARK_NAME

Benchmark name. The macro is **not** defined by the header. The build tooling defines it from the enclosing package name (e.g., `-DBENCHMARK_NAME="@stdlib/math/base/special/abs"`), and a benchmark file should define a fallback:

```c
#ifndef BENCHMARK_NAME
#define BENCHMARK_NAME "abs"
#endif
```

#### STDLIB_BENCH { ... }

Macro for defining the main execution sequence. The macro expands to a generated `main` function which seeds the C standard library pseudorandom number generator, prints the TAP version, runs the block (as the body of a static function `stdlib_bench_main`), and prints the TAP summary.

```c
STDLIB_BENCH {
STDLIB_BENCH_PREAMBLE( 3, 1000000 ) {
STDLIB_BENCH_PRINT_NAME();
STDLIB_RUN_BENCHMARK( benchmark );
}
}
```

#### STDLIB_BENCH_PREAMBLE( repeats, iterations ) { ... }

Macro for running a block `repeats` times with a fixed number of iterations. Within the block, benchmark functions defined via `STDLIB_BENCHMARK` should be run via `STDLIB_RUN_BENCHMARK`.

```c
STDLIB_BENCH_PREAMBLE( 3, 1000000 ) {
STDLIB_BENCH_PRINT_NAME();
STDLIB_RUN_BENCHMARK( benchmark );
}
```

#### STDLIB_BENCH_LENGTH_PREAMBLE( repeats, iterations, min, max ) { ... }

Macro for running a block `repeats` times for each array length `10^min`, `10^(min+1)`, ..., `10^max`. Within the block, `len` is defined and equal to the current array length, and benchmark functions defined via `STDLIB_LENGTH_BENCHMARK` should be run via `STDLIB_RUN_LENGTH_BENCHMARK`. The number of iterations for a given length is `iterations / 10^(exponent-1)`.

```c
STDLIB_BENCH_LENGTH_PREAMBLE( 3, 10000000, 1, 6 ) {
STDLIB_BENCH_PRINT_NAME_FORMAT( "len=%d", len );
STDLIB_RUN_LENGTH_BENCHMARK( benchmark );
}
```

#### STDLIB_BENCH_PRINT_NAME()

Macro for printing a benchmark name (`# c::<BENCHMARK_NAME>`).

```c
STDLIB_BENCH_PRINT_NAME();
```

#### STDLIB_BENCH_PRINT_NAME_FORMAT( fmt, ... )

Macro for printing a benchmark name with a formatted suffix (`# c::<BENCHMARK_NAME>:<suffix>`). At least one format argument must be provided.

```c
STDLIB_BENCH_PRINT_NAME_FORMAT( "len=%d", len );
```

#### STDLIB_RUN_BENCHMARK( fn )

Macro for running a benchmark function defined via `STDLIB_BENCHMARK` and printing its results. Must be used within a `STDLIB_BENCH_PREAMBLE` block.

```c
STDLIB_RUN_BENCHMARK( benchmark );
```

#### STDLIB_RUN_LENGTH_BENCHMARK( fn )

Macro for running a length-based benchmark function defined via `STDLIB_LENGTH_BENCHMARK` and printing its results. Must be used within a `STDLIB_BENCH_LENGTH_PREAMBLE` block.

```c
STDLIB_RUN_LENGTH_BENCHMARK( benchmark );
```

#### STDLIB_BENCHMARK( fn ) { ... }

Macro for defining a benchmark function. Within the block, `iterations` is defined. The block must contain `STDLIB_BENCHMARK_LOOP_PREAMBLE`, `STDLIB_BENCHMARK_LOOP_EPILOGUE`, and `STDLIB_BENCHMARK_EPILOGUE`, in that order.

```c
STDLIB_BENCHMARK( benchmark ) {
double y = 0.0;

STDLIB_BENCHMARK_LOOP_PREAMBLE {
y = sqrt( stdlib_bench_random_uniform( 0.0, 100.0 ) );
if ( y != y ) {
printf( "should not return NaN\n" );
break;
}
}
STDLIB_BENCHMARK_LOOP_EPILOGUE;
if ( y != y ) {
printf( "should not return NaN\n" );
}
STDLIB_BENCHMARK_EPILOGUE;
}
```

#### STDLIB_LENGTH_BENCHMARK( fn ) { ... }

Macro for defining a length-based benchmark function. Within the block, `iterations` and `len` (array length) are defined. The block must contain `STDLIB_BENCHMARK_LOOP_PREAMBLE`, `STDLIB_BENCHMARK_LOOP_EPILOGUE`, and `STDLIB_BENCHMARK_EPILOGUE`, in that order.

```c
STDLIB_LENGTH_BENCHMARK( benchmark ) {
double y = 0.0;

STDLIB_BENCHMARK_MALLOC_ARRAY_FLOAT64( x, len );
STDLIB_BENCHMARK_FILL_ARRAY( x, len, stdlib_bench_random_uniform( -100.0, 100.0 ) );

STDLIB_BENCHMARK_LOOP_PREAMBLE {
y = x[ i%len ];
if ( y != y ) {
printf( "should not return NaN\n" );
break;
}
}
STDLIB_BENCHMARK_LOOP_EPILOGUE;
if ( y != y ) {
printf( "should not return NaN\n" );
}
STDLIB_BENCHMARK_FREE( x );
STDLIB_BENCHMARK_EPILOGUE;
}
```

#### STDLIB_BENCHMARK_LOOP_PREAMBLE { ... }

Macro for starting a benchmark timer and beginning the benchmark loop. Within the block, `i` is defined and equal to the current iteration.

#### STDLIB_BENCHMARK_LOOP_EPILOGUE

Macro for stopping a benchmark timer. Teardown code (e.g., freeing arrays) should follow this macro.

#### STDLIB_BENCHMARK_EPILOGUE

Macro for returning the elapsed time from a benchmark function.

#### STDLIB_BENCHMARK_MALLOC_ARRAY( type, x, n )

Macro for declaring a pointer `x` and allocating an array of `n` elements of type `type`.

```c
STDLIB_BENCHMARK_MALLOC_ARRAY( double, x, 100 );
```

#### STDLIB_BENCHMARK_MALLOC_ARRAY_FLOAT64( x, n )

Macro for declaring a pointer `x` and allocating a double-precision floating-point array of `n` elements.

```c
STDLIB_BENCHMARK_MALLOC_ARRAY_FLOAT64( x, 100 );
```

#### STDLIB_BENCHMARK_MALLOC_ARRAY_FLOAT32( x, n )

Macro for declaring a pointer `x` and allocating a single-precision floating-point array of `n` elements.

```c
STDLIB_BENCHMARK_MALLOC_ARRAY_FLOAT32( x, 100 );
```

#### STDLIB_BENCHMARK_FILL_STRIDED_ARRAY( x, n, stride, value )

Macro for filling `n` indexed elements of a strided array with a value. The value expression is evaluated once per indexed element. Following stdlib strided array conventions, a negative stride fills the array starting from the last indexed element.

```c
STDLIB_BENCHMARK_FILL_STRIDED_ARRAY( x, 50, 2, stdlib_bench_random_uniform( -10.0, 10.0 ) );
```

#### STDLIB_BENCHMARK_FILL_ARRAY( x, n, value )

Macro for filling an array with a value. The value expression is evaluated once per element.

```c
STDLIB_BENCHMARK_FILL_ARRAY( x, 100, stdlib_bench_random_uniform( -10.0, 10.0 ) );
```

#### STDLIB_BENCHMARK_FREE( x )

Macro for freeing an array allocated via `STDLIB_BENCHMARK_MALLOC_ARRAY*`.

```c
STDLIB_BENCHMARK_FREE( x );
```

#### stdlib_bench_print_version()

Prints the TAP version.

```c
stdlib_bench_print_version();
```

```c
void stdlib_bench_print_version( void );
```

#### stdlib_bench_print_summary( total, passing )

Prints the TAP summary.

```c
stdlib_bench_print_summary( 3, 3 );
```

The function accepts the following arguments:

- **total**: `[in] int` total number of tests.
- **passing**: `[in] int` total number of passing tests.

```c
void stdlib_bench_print_summary( const int total, const int passing );
```

#### stdlib_bench_print_results( iterations, elapsed )

Prints benchmark results.

```c
stdlib_bench_print_results( 1000000, 0.5 );
```

The function accepts the following arguments:

- **iterations**: `[in] int` number of iterations.
- **elapsed**: `[in] double` elapsed time in seconds.

```c
void stdlib_bench_print_results( const int iterations, const double elapsed );
```

#### stdlib_bench_tic()

Returns a clock time.

```c
double t = stdlib_bench_tic();
```

```c
double stdlib_bench_tic( void );
```

#### stdlib_bench_rand_float64()

Generates a random double-precision floating-point number on the interval `[0,1)`.

```c
double r = stdlib_bench_rand_float64();
```

```c
double stdlib_bench_rand_float64( void );
```

#### stdlib_bench_rand_float32()

Generates a random single-precision floating-point number on the interval `[0,1)`.

```c
float r = stdlib_bench_rand_float32();
```

```c
float stdlib_bench_rand_float32( void );
```

#### stdlib_bench_random_uniform( min, max )

Generates a random double-precision floating-point number drawn from a uniform distribution on the interval `[min,max)`.

```c
double r = stdlib_bench_random_uniform( -10.0, 10.0 );
```

The function accepts the following arguments:

- **min**: `[in] double` minimum value (inclusive).
- **max**: `[in] double` maximum value (exclusive).

```c
double stdlib_bench_random_uniform( const double min, const double max );
```

</section>

<!-- /.usage -->

<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->

<section class="notes">

### Notes

- The harness exposes the following identifiers to benchmark code: `iterations` (within benchmark functions), `i` (within benchmark loops), and `len` (within `STDLIB_BENCH_LENGTH_PREAMBLE` blocks and length-based benchmark functions). Every other identifier introduced by the harness is prefixed with `stdlib_bench_` (functions and variables) or `STDLIB_BENCH_` / `STDLIB_BENCHMARK_` (macros), with `STDLIB_RUN_BENCHMARK` and `STDLIB_RUN_LENGTH_BENCHMARK` as the exceptions (their names follow the JavaScript harness's `bench()`/`benchmark()` pairing).
- `STDLIB_BENCH` must appear after every benchmark function it runs, as `STDLIB_RUN_BENCHMARK` and `STDLIB_RUN_LENGTH_BENCHMARK` call the function directly.
- The header depends only on the C standard library.
- The `stdlib_bench_print_*` and `stdlib_bench_tic` helpers are invoked by the harness macros; benchmark code does not normally call them directly.

</section>

<!-- /.notes -->

<!-- C API usage examples. -->

<section class="examples">

### Examples

```c
#include "stdlib/bench.h"
#include <stdio.h>
#include <math.h>

#ifndef BENCHMARK_NAME
#define BENCHMARK_NAME "sqrt"
#endif

#define ITERATIONS 1000000
#define REPEATS 3

STDLIB_BENCHMARK( benchmark ) {
double y = 0.0;

STDLIB_BENCHMARK_LOOP_PREAMBLE {
y = sqrt( stdlib_bench_random_uniform( 0.0, 100.0 ) );
if ( y != y ) {
printf( "should not return NaN\n" );
break;
}
}
STDLIB_BENCHMARK_LOOP_EPILOGUE;
if ( y != y ) {
printf( "should not return NaN\n" );
}
STDLIB_BENCHMARK_EPILOGUE;
}

STDLIB_BENCH {
STDLIB_BENCH_PREAMBLE( REPEATS, ITERATIONS ) {
STDLIB_BENCH_PRINT_NAME();
STDLIB_RUN_BENCHMARK( benchmark );
}
}
```

</section>

<!-- /.examples -->

</section>

<!-- /.c -->

<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->

<section class="references">
Expand Down Expand Up @@ -92,6 +476,8 @@ This function is an alias for [@stdlib/bench/harness][@stdlib/bench/harness].

[@stdlib/bench/harness]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/bench/harness

[tap]: https://testanything.org/

<!-- <related-links> -->

[@stdlib/utils/timeit]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/utils/timeit
Expand Down
Loading
Loading