/**
* @file include/benchmarking.h
* @brief Define macros for benchmarking
*/
#pragma once
#ifdef BENCHMARK_MODE
#include "ansiesc.h"
#include "def.h"
#include <stdio.h>
#include <time.h>
#ifndef REPEAT
#define REPEAT 10'000
#endif
#define CADR(...) CAR(CDR(__VA_ARGS__))
#define BENCH_HEADER " ■ " ESCBLU "Benchmarking " ESCLR
#define BENCH_TEMPLATE(name, identifier, time_fn_pair) \
static void bench__bench##identifier(); \
[[gnu::constructor]] static void bench__run##identifier() { \
printf(BENCH_HEADER ESBLD #name ESCLR "..."); \
double begin = (double)CAR time_fn_pair; \
for (int i = 0; i < REPEAT; i++) [[clang::always_inline]] \
bench__bench##identifier(); \
double val = (double)CAR time_fn_pair - begin; \
printf(" => %.6f " CADR time_fn_pair "\n", val / REPEAT); \
} \
static void bench__bench##identifier()
#define bench(name) BENCH_TEMPLATE(name, name##bench, (clock(), "microsecs"))
#define bench_cycle(name) \
BENCH_TEMPLATE( \
name, name##benchcycle, (__builtin_readcyclecounter(), "cycle") \
)
#define main bench__dummymain
#else
// --gc-sections
#define bench(a) [[gnu::unused]] static void BENCH_dum##a()
#define bench_cycle(a) [[gnu::unused]] static void BENCH_dumc##a()
#endif