bench: real black_box barrier + three-signal growth-curve gate
Adds el_black_box (inline asm, +r constraint, memory clobber) and runtime/elbench.el: a growth-curve classifier that gates time AND allocation-count AND allocation-bytes, failing if any exceeds its declared curve. Refusal is a first-class verdict. The classifier REFUSES rather than classifying when the largest measurement is below the floor, or when a series is hard-flat across an 8x input range -- the shape produced when the optimiser deletes the work. Reporting O(1) there would be a confident answer with nothing behind it. Disagreeing ratios report INDETERMINATE rather than a guess. Deviation from DESIGN.md 6.2, stated in the source: uses consecutive ratios on a mandated geometric sweep rather than least-squares over candidate curves. Ratios are directly interpretable on a doubling sweep and need no floating point; the cost is weaker O(n) vs O(n log n) separation, reported as an ambiguous band rather than guessed. Documents the counter scope limit: engram_*.c and libcurl malloc are NOT tracked, so a flat curve over engram/HTTP-dominated work is not evidence of anything. 13 tests prove the classifier against real measured series from fitprobe.el -- including that an accumulator's allocation COUNT is linear while its bytes are quadratic, and that el #132's pure-CPU shape reads FLAT on both allocation signals and is caught only by time.
This commit is contained in:
@@ -18522,6 +18522,26 @@ el_val_t engram_pool_stats_json(void) {
|
||||
el_val_t el_alloc_count(void) { return (el_val_t)(int64_t)_el_alloc_count; }
|
||||
el_val_t el_alloc_bytes(void) { return (el_val_t)(int64_t)_el_alloc_bytes; }
|
||||
|
||||
/* el_black_box — optimisation barrier for benchmark bodies.
|
||||
*
|
||||
* WHY THIS IS NOT OPTIONAL. A benchmark whose result is unused is dead code,
|
||||
* and CONSUMING THE RESULT IS NOT SUFFICIENT: clang recognises loop idioms and
|
||||
* closes them to arithmetic. A nested `total = total + 1` loop measured at
|
||||
* 0 microseconds for every n while returning a numerically correct n*n --
|
||||
* the answer was right and the work never happened.
|
||||
*
|
||||
* That is the same failure shape as a test that never ran reporting pass. The
|
||||
* harness must own the barrier rather than trusting the benchmark author to
|
||||
* defeat the optimiser.
|
||||
*
|
||||
* The constraint "+r" forces the value through a register the compiler must
|
||||
* treat as both read and written by opaque code; the "memory" clobber stops
|
||||
* loads and stores being reordered across it or elided. Emits no instructions. */
|
||||
el_val_t el_black_box(el_val_t v) {
|
||||
__asm__ __volatile__("" : "+r"(v) : : "memory");
|
||||
return v;
|
||||
}
|
||||
|
||||
el_val_t el_peak_rss(void) {
|
||||
struct rusage ru;
|
||||
if (getrusage(RUSAGE_SELF, &ru) != 0) return (el_val_t)0;
|
||||
|
||||
Reference in New Issue
Block a user