// SafeC Standard Library — Benchmark Framework
#pragma once
#include <std/stddef.h>
#include <std/test/bench.h>
namespace std {
extern int printf(const char* fmt, ...);
extern long clock(); // returns clock_t; CLOCKS_PER_SEC = 1000000
extern unsigned char* memset(unsigned char* p, int v, size_t n);
#define CLOCKS_PER_SEC_VAL 1000000
static void bench_copy_(char* dst, const char* src, unsigned long n) {
unsafe {
unsigned long i = (unsigned long)0;
while (i < n - (unsigned long)1 && src[i] != '\0') {
dst[i] = src[i];
i = i + (unsigned long)1;
}
dst[i] = '\0';
}
}
struct BenchSuite BenchSuite::new() {
struct BenchSuite s;
s.count = 0;
return s;
}
void BenchSuite::add_raw_(const &char name, fn void(?&Erased) func, ?&Erased arg, unsigned long iters) {
if (self.count >= BENCH_MAX) { return; }
int idx = self.count;
unsafe { bench_copy_(self.cases[idx].name, name, (unsigned long)BENCH_NAME_MAX); }
self.cases[idx].func = func;
self.cases[idx].arg = arg;
self.cases[idx].iters = iters;
self.cases[idx].elapsed_s = 0.0;
self.cases[idx].ops_per_s = 0.0;
self.count = self.count + 1;
}
void BenchSuite::run() {
int i = 0;
while (i < self.count) {
unsigned long n = self.cases[i].iters;
unsafe {
long t0 = clock();
unsigned long j = (unsigned long)0;
while (j < n) {
self.cases[i].func(self.cases[i].arg);
j = j + (unsigned long)1;
}
long t1 = clock();
double elapsed = (double)(t1 - t0) / (double)CLOCKS_PER_SEC_VAL;
self.cases[i].elapsed_s = elapsed;
if (elapsed > 0.0) {
self.cases[i].ops_per_s = (double)n / elapsed;
}
}
i = i + 1;
}
}
void BenchSuite::print_results() const {
unsafe {
printf("%-40s %10s %14s %14s\n",
"benchmark", "iters", "elapsed (s)", "ops/s");
printf("%-40s %10s %14s %14s\n",
"─────────────────────────────────────────",
"──────────", "─────────────", "─────────────");
int i = 0;
while (i < self.count) {
printf("%-40s %10llu %14.6f %14.0f\n",
self.cases[i].name,
(unsigned long long)self.cases[i].iters,
self.cases[i].elapsed_s,
self.cases[i].ops_per_s);
i = i + 1;
}
}
}
} // namespace std