runners: bench: Added BENCH_SIMTIME/SIMRESET/PAUSE/RESUME/etc

- BENCH_SIMTIME()   => lfs3_kiwibd_simtime()
- BENCH_SIMRESET()  => lfs3_kiwibd_simreset()
- BENCH_SIMPAUSE()  => lfs3_kiwibd_simpause()
- BENCH_SIMRESUME() => lfs3_kiwibd_simresume()
- BENCH_RESET()     => lfs3_kiwibd_simreset() + BENCH_STACK/HEAP_RESET()
- BENCH_PAUSE()     => lfs3_kiwibd_simpause() + BENCH_STACK/HEAP_PAUSE()
- BENCH_RESUME()    => lfs3_kiwibd_simresume() + BENCH_STACK/HEAP_RESUME()

This does two things:

1. Adds pause/resume counters to bd counters to make it easier to
   exclude operations from the current bench (potentially useful for
   seq+disk usage).

2. Exposes bd simtime operations as BENCH_* macros, to make it a bit
   easier to interact with simtime without tying all the benches to
   kiwibd. (Not that we'll ever probably not use kiwibd, but still).

Also adopted 32-bit counters for stack/heap pause state instead of a
32-bit stack. Not that either are at a risk of overflowing, but better
safe than sorry.
This commit is contained in:
Christopher Haster
2026-02-07 20:02:26 -06:00
parent f62d91c9b5
commit 10e77d9177
12 changed files with 325 additions and 119 deletions
+137 -43
View File
@@ -24,20 +24,6 @@
#include <stddef.h>
// some common types
#ifndef BENCH_KIWIBD
typedef lfs3_emubd_io_t bench_io_t;
typedef lfs3_emubd_sio_t bench_sio_t;
typedef lfs3_emubd_ns_t bench_ns_t;
typedef lfs3_emubd_sns_t bench_sns_t;
#else
typedef lfs3_kiwibd_io_t bench_io_t;
typedef lfs3_kiwibd_sio_t bench_sio_t;
typedef lfs3_kiwibd_ns_t bench_ns_t;
typedef lfs3_kiwibd_sns_t bench_sns_t;
#endif
// some helpers
// append to an array with amortized doubling
@@ -625,7 +611,8 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size) {
// stack hooks
#ifdef BENCH_STACK
uint32_t bench_stack_entered = 0;
uint32_t bench_stack_entered = false;
uint32_t bench_stack_paused = false;
uint8_t *bench_stack_entrance = NULL;
size_t bench_stack_watermark = 0;
#endif
@@ -634,7 +621,8 @@ size_t bench_stack_watermark = 0;
#ifdef BENCH_STACK
__attribute__((noinline))
void bench_stack_enter(void) {
bench_stack_entered = 1;
bench_stack_entered = true;
bench_stack_paused = false;
bench_stack_entrance = __builtin_frame_address(0);
bench_stack_watermark = 0;
}
@@ -642,7 +630,14 @@ void bench_stack_enter(void) {
#ifdef BENCH_STACK
void bench_stack_exit(void) {
bench_stack_entered = 0;
assert(bench_stack_entered);
bench_stack_entered = false;
}
#endif
#ifdef BENCH_STACK
void bench_stack_reset(void) {
bench_stack_watermark = 0;
}
#endif
@@ -650,7 +645,7 @@ void bench_stack_exit(void) {
#ifdef BENCH_STACK
__attribute__((noinline))
void bench_stack_pause(void) {
if (bench_stack_entered & 1) {
if (bench_stack_entered && !bench_stack_paused) {
uint8_t *current = __builtin_frame_address(0);
// keep track of the deepest stack
@@ -664,14 +659,14 @@ void bench_stack_pause(void) {
}
}
// haha, a little 32-bit stack
bench_stack_entered <<= 1;
bench_stack_paused += 1;
}
#endif
#ifdef BENCH_STACK
void bench_stack_resume(void) {
bench_stack_entered >>= 1;
assert(bench_stack_paused);
bench_stack_paused -= 1;
}
#endif
@@ -695,7 +690,8 @@ size_t bench_stack_current(void) {
// heap hooks
#ifdef BENCH_HEAP
uint32_t bench_heap_entered = 0;
uint32_t bench_heap_entered = false;
uint32_t bench_heap_paused = false;
size_t bench_heap_current = 0;
size_t bench_heap_watermark = 0;
#endif
@@ -703,7 +699,8 @@ size_t bench_heap_watermark = 0;
// call me when entering/exiting a bench!
#ifdef BENCH_HEAP
void bench_heap_enter(void) {
bench_heap_entered = 1;
bench_heap_entered = true;
bench_heap_paused = false;
bench_heap_current = 0;
bench_heap_watermark = 0;
}
@@ -711,31 +708,34 @@ void bench_heap_enter(void) {
#ifdef BENCH_HEAP
void bench_heap_exit(void) {
bench_heap_entered = 0;
if (bench_heap_watermark != 0) {
fprintf(stderr, "warning: memory leak detected (%zd > 0)\n",
bench_heap_watermark);
}
assert(bench_heap_entered);
bench_heap_entered = false;
}
#endif
#ifdef BENCH_HEAP
void bench_heap_reset(void) {
bench_heap_watermark = 0;
}
#endif
// call me when entering/exiting a bd op!
#ifdef BENCH_HEAP
void bench_heap_pause(void) {
// haha, a little 32-bit stack
bench_heap_entered <<= 1;
bench_heap_paused += 1;
}
#endif
#ifdef BENCH_HEAP
void bench_heap_resume(void) {
bench_heap_entered >>= 1;
assert(bench_heap_paused);
bench_heap_paused -= 1;
}
#endif
#ifdef BENCH_HEAP
void bench_heap_inc(size_t size) {
if (bench_heap_entered & 1) {
if (bench_heap_entered && !bench_heap_paused) {
bench_heap_current += size;
// keep track of the deepest heap
if (bench_heap_current > bench_heap_watermark) {
@@ -747,9 +747,8 @@ void bench_heap_inc(size_t size) {
#ifdef BENCH_HEAP
void bench_heap_dec(size_t size) {
if (bench_heap_entered & 1) {
assert(bench_heap_current >= size);
bench_heap_current -= size;
if (bench_heap_entered && !bench_heap_paused) {
bench_heap_current -= lfs3_min(size, bench_heap_current);
}
}
#endif
@@ -885,11 +884,16 @@ static bench_record_t *bench_records;
size_t bench_record_count;
size_t bench_record_capacity;
void bench_reset(const struct lfs3_cfg *cfg) {
void bench_init(const struct lfs3_cfg *cfg) {
bench_cfg = cfg;
bench_record_count = 0;
}
void bench_deinit(const struct lfs3_cfg *cfg) {
(void)cfg;
// do nothing
}
void bench_start(const char *probe) {
BENCH_STACK_PAUSE();
BENCH_HEAP_PAUSE();
@@ -1091,6 +1095,95 @@ void bench_fresult(const char *probe, uintmax_t n, double result) {
BENCH_STACK_RESUME();
}
bench_ns_t bench_simtime(void) {
// get the current simtime
assert(bench_cfg);
#ifndef BENCH_KIWIBD
// note this can error if no timings provided
bench_sns_t simtime = lfs3_emubd_simtime(bench_cfg);
assert(simtime >= 0);
#else
// note this can error if no timings provided
bench_sns_t simtime = lfs3_kiwibd_simtime(bench_cfg);
assert(simtime >= 0);
#endif
return simtime;
}
void bench_simreset(void) {
// reset bd
#ifndef BENCH_KIWIBD
int err = lfs3_emubd_simreset(bench_cfg);
assert(!err);
#else
int err = lfs3_kiwibd_simreset(bench_cfg);
assert(!err);
#endif
}
void bench_simpause(void) {
// pause bd simulation
#ifndef BENCH_KIWIBD
int err = lfs3_emubd_simpause(bench_cfg);
assert(!err);
#else
int err = lfs3_kiwibd_simpause(bench_cfg);
assert(!err);
#endif
}
void bench_simresume(void) {
// resume bd simulation
#ifndef BENCH_KIWIBD
int err = lfs3_emubd_simresume(bench_cfg);
assert(!err);
#else
int err = lfs3_kiwibd_simresume(bench_cfg);
assert(!err);
#endif
}
void bench_reset(void) {
// reset bd
bench_simreset();
// reset stack/heap measurements
#ifdef BENCH_HEAP
bench_heap_reset();
#endif
#ifdef BENCH_STACK
bench_stack_reset();
#endif
}
void bench_pause(void) {
// pause stack/heap measurements
#ifdef BENCH_STACK
bench_stack_pause();
#endif
#ifdef BENCH_HEAP
bench_heap_pause();
#endif
// pause bd simulation
bench_simpause();
}
void bench_resume(void) {
// resume bd simulation
bench_simresume();
// resume stack/heap measurements
#ifdef BENCH_HEAP
bench_heap_resume();
#endif
#ifdef BENCH_STACK
bench_stack_resume();
#endif
}
// encode our permutation into a reusable id
static void perm_printid(
@@ -1868,22 +1961,23 @@ void perm_run(
printf("running ");
perm_printid(suite, case_);
printf("\n");
bench_reset(CFG);
#ifdef BENCH_STACK
bench_stack_enter();
#endif
bench_init(CFG);
#ifdef BENCH_HEAP
bench_heap_enter();
#endif
#ifdef BENCH_STACK
bench_stack_enter();
#endif
case_->run(CFG);
#ifdef BENCH_HEAP
bench_heap_exit();
#endif
#ifdef BENCH_STACK
bench_stack_exit();
#endif
#ifdef BENCH_HEAP
bench_heap_exit();
#endif
bench_deinit(CFG);
printf("finished ");
perm_printid(suite, case_);
printf("\n");
+36
View File
@@ -78,6 +78,19 @@ void bench_trace(const char *fmt, ...);
#undef _STDIO_H
// some common types
#ifndef BENCH_KIWIBD
typedef lfs3_emubd_io_t bench_io_t;
typedef lfs3_emubd_sio_t bench_sio_t;
typedef lfs3_emubd_ns_t bench_ns_t;
typedef lfs3_emubd_sns_t bench_sns_t;
#else
typedef lfs3_kiwibd_io_t bench_io_t;
typedef lfs3_kiwibd_sio_t bench_sio_t;
typedef lfs3_kiwibd_ns_t bench_ns_t;
typedef lfs3_kiwibd_sns_t bench_sns_t;
#endif
// generated bench configurations
struct lfs3_cfg;
@@ -138,6 +151,24 @@ void bench_fresult(const char *probe, uintmax_t n, double result);
#define BENCH_RESULT(probe, n, result) bench_result(probe, n, result)
#define BENCH_FRESULT(probe, n, result) bench_fresult(probe, n, result)
// extra hooks to get the current simtime, pause readed/progged/erased
// counters, etc
bench_ns_t bench_simtime(void);
void bench_simreset(void);
void bench_simpause(void);
void bench_simresume(void);
void bench_reset(void);
void bench_pause(void);
void bench_resume(void);
#define BENCH_SIMTIME() bench_simtime()
#define BENCH_SIMRESET() bench_simreset()
#define BENCH_SIMPAUSE() bench_simpause()
#define BENCH_SIMRESUME() bench_simresume()
#define BENCH_RESET() bench_reset()
#define BENCH_PAUSE() bench_pause()
#define BENCH_RESUME() bench_resume()
// deterministic prng for pseudo-randomness in benches
uint32_t bench_prng(uint32_t *state);
@@ -155,15 +186,18 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size);
// get the maximum/current stack usage for this run
extern size_t bench_stack_watermark;
__attribute__((noinline)) size_t bench_stack_current(void);
void bench_stack_reset(void);
__attribute__((noinline)) void bench_stack_pause(void);
void bench_stack_resume(void);
#define BENCH_STACK_WATERMARK() bench_stack_watermark
#define BENCH_STACK_CURRENT() bench_stack_current()
#define BENCH_STACK_RESET() bench_stack_reset()
#define BENCH_STACK_PAUSE() bench_stack_pause()
#define BENCH_STACK_RESUME() bench_stack_resume()
#else
// stubs if not measuring stack
#define BENCH_STACK_RESET()
#define BENCH_STACK_PAUSE()
#define BENCH_STACK_RESUME()
#endif
@@ -179,12 +213,14 @@ void bench_heap_dec(size_t size);
#define BENCH_HEAP_WATERMARK() bench_heap_watermark
#define BENCH_HEAP_CURRENT() bench_heap_current
#define BENCH_HEAP_RESET() bench_heap_reset()
#define BENCH_HEAP_PAUSE() bench_heap_pause()
#define BENCH_HEAP_RESUME() bench_heap_resume()
#define BENCH_HEAP_INC(size) bench_heap_inc(size)
#define BENCH_HEAP_DEC(size) bench_heap_dec(size)
#else
// stubs if not measuring heap
#define BENCH_HEAP_RESET()
#define BENCH_HEAP_PAUSE()
#define BENCH_HEAP_RESUME()
#define BENCH_HEAP_INC(size)
-14
View File
@@ -24,20 +24,6 @@
#include <stddef.h>
// some common types
#ifndef TEST_KIWIBD
typedef lfs3_emubd_ns_t test_ns_t;
typedef lfs3_emubd_sns_t test_sns_t;
typedef lfs3_emubd_powercycles_t test_powercycles_t;
typedef lfs3_emubd_spowercycles_t test_spowercycles_t;
#else
typedef lfs3_kiwibd_ns_t test_ns_t;
typedef lfs3_kiwibd_sns_t test_sns_t;
typedef void test_powercycles_t;
typedef void test_spowercycles_t;
#endif
// some helpers
// append to an array with amortized doubling
+13
View File
@@ -78,6 +78,19 @@ void test_trace(const char *fmt, ...);
#undef _STDIO_H
// some common types
#ifndef TEST_KIWIBD
typedef lfs3_emubd_ns_t test_ns_t;
typedef lfs3_emubd_sns_t test_sns_t;
typedef lfs3_emubd_powercycles_t test_powercycles_t;
typedef lfs3_emubd_spowercycles_t test_spowercycles_t;
#else
typedef lfs3_kiwibd_ns_t test_ns_t;
typedef lfs3_kiwibd_sns_t test_sns_t;
typedef void test_powercycles_t;
typedef void test_spowercycles_t;
#endif
// generated test configurations
struct lfs3_cfg;