runners: Added stack/heap measurement functions
These have been battle-tested in external benchmarks, and have proven useful for finding a runtime estimate on stack+heap usage. Of course, to be realistic they need to be cross-compiled and run under QEMU (which does work!), but even on x86_64 they provide a nice insight into RAM usage. In practice the only real difference is pointer width anyways. --- Enabled by default for the bench runner, these are available if TEST/BENCH_YES_HEAP and/or TEST/BENCH_YES_STACK are defined. (This default is provided by the Makefile. At least heap measurements rely on linker flags, so it probably doesn't make sense to default enable in the bench runner itself.) Stack vs heap rely on slightly different mechanisms: - Stack: Uses GCC's __builtin_frame_address(0) to measure the current stack usage on entry to every bd operation. - Heap: Relies on GCC's -Wl,--wrap flags to intercept every malloc/free call, to track the current heap usage. These are available via bench/test macros: - BENCH_STACK() - Maximum stack usage of the current run - BENCH_STACK_CURRENT() - Current stack usage - BENCH_HEAP() - Maximum heap usage of the current run - BENCH_HEAP_CURRENT() - Current heap usage Note BENCH_STACK_CURRENT() can be useful for separating out the bench's ctx from total stack usage, similarly to our static analysis. --- One surprising outcome is that these heap hooks trivially implement a memory leak detector. Maybe that could be useful in the test_runner as a cheaper alternative to Valgrind?
This commit is contained in:
@@ -115,6 +115,34 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size);
|
||||
#define TEST_FACTORIAL(x) test_factorial(x)
|
||||
#define TEST_PERMUTATION(i, buffer, size) test_permutation(i, buffer, size)
|
||||
|
||||
#ifdef TEST_YES_STACK
|
||||
// get the maximum/current stack usage for this run
|
||||
size_t test_stack(void);
|
||||
__attribute__((noinline))
|
||||
size_t test_stack_current(void);
|
||||
__attribute__((noinline))
|
||||
void test_stack_pause(void);
|
||||
void test_stack_resume(void);
|
||||
|
||||
#define TEST_STACK() test_stack()
|
||||
#define TEST_STACK_CURRENT() test_stack_current()
|
||||
#define TEST_STACK_PAUSE() test_stack_pause()
|
||||
#define TEST_STACK_RESUME() test_stack_resume()
|
||||
#endif
|
||||
|
||||
#ifdef TEST_YES_HEAP
|
||||
// get the maximum/current heap usage for this run
|
||||
size_t test_heap(void);
|
||||
size_t test_heap_current(void);
|
||||
void test_heap_pause(void);
|
||||
void test_heap_resume(void);
|
||||
|
||||
#define TEST_HEAP() test_heap()
|
||||
#define TEST_HEAP_CURRENT() test_heap_current()
|
||||
#define TEST_HEAP_PAUSE() test_heap_pause()
|
||||
#define TEST_HEAP_RESUME() test_heap_resume()
|
||||
#endif
|
||||
|
||||
|
||||
// declare implicit defines as global intmax_ts
|
||||
#define TEST_DEFINE(k, v) \
|
||||
|
||||
Reference in New Issue
Block a user