mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
80 lines
2.5 KiB
C
80 lines
2.5 KiB
C
#ifndef COSMOPOLITAN_LIBC_TESTLIB_BENCHMARK_H_
|
|
#define COSMOPOLITAN_LIBC_TESTLIB_BENCHMARK_H_
|
|
#include "libc/calls/struct/timespec.h"
|
|
#include "libc/stdio/stdio.h"
|
|
COSMOPOLITAN_C_START_
|
|
|
|
#define X(x) __expropriate(x)
|
|
#define V(x) __veil("r", x)
|
|
|
|
#define BENCHMARK(ITERATIONS, WORK_PER_RUN, CODE) \
|
|
do { \
|
|
struct timespec start = timespec_real(); \
|
|
for (int __i = 0; __i < ITERATIONS; ++__i) { \
|
|
asm volatile("" ::: "memory"); \
|
|
CODE; \
|
|
} \
|
|
long ns = timespec_tonanos(timespec_sub(timespec_real(), start)); \
|
|
_print_benchmark_result(ns, WORK_PER_RUN, ITERATIONS, #CODE); \
|
|
} while (0)
|
|
|
|
static void _print_benchmark_result(double total_nanos, double work_per_run,
|
|
int iterations, const char* code) {
|
|
double time_per_op = total_nanos / (work_per_run * iterations);
|
|
double throughput = work_per_run / (total_nanos / iterations * 1e-9);
|
|
|
|
const char* throughput_unit;
|
|
const char* time_unit;
|
|
double time_value;
|
|
|
|
// Determine throughput unit
|
|
if (throughput >= 1e9) {
|
|
throughput /= 1e9;
|
|
throughput_unit = "G";
|
|
} else if (throughput >= 1e6) {
|
|
throughput /= 1e6;
|
|
throughput_unit = "M";
|
|
} else if (throughput >= 1e3) {
|
|
throughput /= 1e3;
|
|
throughput_unit = "K";
|
|
} else {
|
|
throughput_unit = " ";
|
|
}
|
|
|
|
// Determine time unit
|
|
if (time_per_op >= 1e6) {
|
|
time_value = time_per_op / 1e6;
|
|
time_unit = "ms";
|
|
} else if (time_per_op >= 1e3) {
|
|
time_value = time_per_op / 1e3;
|
|
time_unit = "µs";
|
|
} else if (time_per_op >= .01) {
|
|
time_value = time_per_op;
|
|
time_unit = "ns";
|
|
} else {
|
|
time_value = time_per_op * 1e3;
|
|
time_unit = "ps";
|
|
}
|
|
|
|
// Determine work unit
|
|
const char* work_unit;
|
|
if (work_per_run >= 1e9) {
|
|
work_per_run /= 1e9;
|
|
work_unit = "G";
|
|
} else if (work_per_run >= 1e6) {
|
|
work_per_run /= 1e6;
|
|
work_unit = "M";
|
|
} else if (work_per_run >= 1e3) {
|
|
work_per_run /= 1e3;
|
|
work_unit = "K";
|
|
} else {
|
|
work_unit = " ";
|
|
}
|
|
|
|
printf("%8.2f %-2s %8.2f %s/s %6.2f %s %3dx %s\n", time_value, time_unit,
|
|
throughput, throughput_unit, work_per_run, work_unit, iterations,
|
|
code);
|
|
}
|
|
|
|
COSMOPOLITAN_C_END_
|
|
#endif /* COSMOPOLITAN_LIBC_TESTLIB_BENCHMARK_H_ */
|