code wiki / (root) / nx_bench_core.nx

nx_bench_core.nx source

↩ module page · 212 lines · 9075 B

1// nx_bench_core.nx -- B1 second stone of NISHI_PERFORMANCE_ 2// DOCTRINE_ROADMAP.md. 3// 4// Shippable bench harness primitive: warmup + N-iteration measurement 5// + reference band check + pathology classification + ETG attestation. 6// Composes nx_etg (E1), nx_perf_pathology (B1 sibling), and 7// nx_clock (existing monotonic timer). 8// 9// Why this brick is the SUBSTRATE BENCH PATTERN: every future bench 10// (CPU matmul, memory copy, NVMe scan, network RTT, GPU kernel) calls 11// this harness with a "workload runner" + a reference band + signals. 12// The harness: 13// 1. Runs N_WARMUP iterations to settle caches / JIT / TLB 14// 2. Runs N_MEASURED iterations capturing per-iteration ns 15// 3. Computes median, p50, p99 (sort then index for B1 first stone; 16// reservoir sampling deferred to B3) 17// 4. Checks if median falls inside the reference (lower, upper) band 18// 5. Calls nx_perf_classify with the signals + in_band flag 19// 6. Emits NxEtgEntry via nx_etg_entry_init with: 20// probe_kind = caller-supplied (cpu/storage/net/gpu/etc.) 21// claim_value = upper bound of the reference band 22// measurement_value = the classified pathology id 23// outcome = derived from pathology (OPTIMAL -> CONFIRMED, 24// anything else -> the 25// ETG outcome that best 26// matches the pathology) 27// 28// Composes: 29// [[NISHI_PERFORMANCE_DOCTRINE_ROADMAP]] B1 30// nx_etg.nx (E1 attestation) 31// nx_perf_pathology.nx (B1 sibling classifier) 32// nx_clock.nx (monotonic timing) 33// [[feedback-hardware-agnostic-is-robustness]] cardinal: this 34// harness must produce identical pathology classifications on 35// identical inputs across ISAs. 36// [[feedback-no-strawman-perf-comparisons]] (no claim without 37// paired measurement; the reference band IS the paired claim) 38// [[feedback-no-false-ok-substrate-honesty-audit]] (INCONCLUSIVE 39// when N too small; never silent) 40 41// nx_safety_envelope: 42// intended_use: "substrate bench harness: warmup + N-iter 43// measurement + pathology classification + 44// ETG attestation; substrate-wide pattern" 45// sil_target: SIL2 46// evidence: [kat_median_band_classification, 47// kat_warmup_does_not_count, 48// kat_inconclusive_when_n_too_small] 49// hazard_register: [bug-tape-sort-quadratic-on-huge-n, 50// bug-tape-warmup-not-applied, 51// bug-tape-band-off-by-one] 52// verdict: NOT_YET_EVALUATED 53 54import "nx_syscalls.nx" 55import "nx_etg.nx" 56import "nx_perf_pathology.nx" 57import "nx_sort.nx" 58 59// ===== Constants ================================================== 60// 61// Substrate-default sample budgets. Caller can override per workload. 62 63const NX_BENCH_DEFAULT_WARMUP: i64 = 5 64const NX_BENCH_DEFAULT_MEASURED: i64 = 17 65const NX_BENCH_MIN_MEASURED: i64 = 3 // below this, INCONCLUSIVE 66 67// Error codes 68const NX_BENCH_ERR_TOO_FEW_SAMPLES: i64 = -1 69const NX_BENCH_ERR_BAD_BAND: i64 = -2 70const NX_BENCH_ERR_ALLOC: i64 = -3 71 72// ===== Bench result struct ======================================== 73// 74// Caller-allocated struct that the harness fills in. 75 76struct NxBenchResult { 77 n_measured: i64, // count of samples kept 78 median_ns: i64, // median of measured samples 79 p99_ns: i64, // 99th percentile (or max if N < 100) 80 min_ns: i64, // fastest sample 81 max_ns: i64, // slowest sample 82 in_band: i64, // 1 if median within (lower, upper); else 0 83 pathology: i64, // NX_PERF_PATH_* 84 pathology_name: *u8, // accessor name 85 attestation_hash: i64, // FNV-1a hash from the emitted NxEtgEntry 86} 87 88// ===== Percentile helpers ========================================= 89// 90// Sort composes [[nx_sort.nx]] (nx_sort_insertion). Previously this 91// file hand-rolled insertion sort inline; refactored 2026-05-20 per 92// the bit-level extension of [[feedback-no-tool-proliferation- 93// consolidate-or-justify]] -- the substrate had 8 inline sort 94// implementations; consolidated here to compose nx_sort. 95 96// Returns the index `i` such that the largest k samples are at 97// indices [n-k, n). Used to pick p99 by counting from the top. 98// p99 of N samples = sample at index (N - 1 - floor(N/100)). 99// For N < 100, p99 collapses to max() which is correct (substrate- 100// honest: with too few samples, p99 == max is the strongest claim). 101func _bench_p99_index(n: i64) -> i64 { 102 if n <= 0 { return -1 } 103 if n < 100 { return n - 1 } 104 let drop: i64 = n / 100 105 return n - 1 - drop 106} 107 108func _bench_median_index(n: i64) -> i64 { 109 if n <= 0 { return -1 } 110 return n / 2 111} 112 113// ===== Iter runner contract ======================================= 114// 115// The caller passes a function pointer that runs ONE iteration of 116// the workload. The runner returns the iteration's elapsed-ns. 117// For B1 first stone we ship a simpler form: caller pre-runs the 118// workload and passes the samples array in directly. The fn-ptr 119// dispatch composes nicely with the parser-bug-fix that landed 120// last session ([[feedback-four-pillar-parser-fnptr-struct- 121// multiarg]]) but for B1 the simpler form lands first. 122 123// ===== Main bench-harness API ===================================== 124// 125// nx_bench_record_samples: 126// Given pre-collected samples (caller-owned i64 array of N ns 127// values), a reference band [lower_ns, upper_ns], a probe_kind 128// for the ETG attestation, and a NxPerfSignals snapshot, 129// compute statistics + classify pathology + emit ETG entry + 130// populate a NxBenchResult. 131// 132// Returns 0 on success, negative on error. 133 134func nx_bench_record_samples( 135 result: *NxBenchResult, 136 entry: *NxEtgEntry, 137 samples: *i64, 138 n_samples: i64, 139 lower_ns: i64, 140 upper_ns: i64, 141 signals: *NxPerfSignals, 142 probe_kind: i64, 143 silicon_serial: i64, 144 selector_version: i64, 145 timestamp_q14: i64 146) -> i64 { 147 if n_samples < NX_BENCH_MIN_MEASURED { return NX_BENCH_ERR_TOO_FEW_SAMPLES } 148 if lower_ns > upper_ns { return NX_BENCH_ERR_BAD_BAND } 149 150 nx_sort_insertion(samples, n_samples) 151 152 let median_idx: i64 = _bench_median_index(n_samples) 153 let p99_idx: i64 = _bench_p99_index(n_samples) 154 let median: i64 = samples[median_idx] 155 let p99: i64 = samples[p99_idx] 156 let min_v: i64 = samples[0] 157 let max_v: i64 = samples[n_samples - 1] 158 159 var in_band: i64 = 0 160 if median >= lower_ns { 161 if median <= upper_ns { 162 in_band = 1 163 } 164 } 165 166 let pathology: i64 = nx_perf_classify(signals, in_band) 167 168 // Map pathology -> ETG outcome. OPTIMAL == CONFIRMED. Any 169 // waste pathology maps to the ETG outcome that best describes 170 // the substrate's relationship with the silicon at this moment. 171 var outcome: i64 = NX_ETG_OUTCOME_INCONCLUSIVE 172 if pathology == NX_PERF_PATH_OPTIMAL { outcome = NX_ETG_OUTCOME_CONFIRMED } 173 if pathology == NX_PERF_PATH_BOTTLENECK_CPU { outcome = NX_ETG_OUTCOME_FALSIFIED } 174 if pathology == NX_PERF_PATH_BOTTLENECK_MEM_BW { outcome = NX_ETG_OUTCOME_FALSIFIED } 175 if pathology == NX_PERF_PATH_BOTTLENECK_MEM_LAT { outcome = NX_ETG_OUTCOME_FALSIFIED } 176 if pathology == NX_PERF_PATH_BOTTLENECK_IO { outcome = NX_ETG_OUTCOME_FALSIFIED } 177 if pathology == NX_PERF_PATH_BLEEDING_LEAKAGE { outcome = NX_ETG_OUTCOME_FALSIFIED } 178 if pathology == NX_PERF_PATH_TOO_MANY_STEPS { outcome = NX_ETG_OUTCOME_FALSIFIED } 179 if pathology == NX_PERF_PATH_TOO_FEW_STEPS { outcome = NX_ETG_OUTCOME_FALSIFIED } 180 if pathology == NX_PERF_PATH_LATENCY_SPIKE { outcome = NX_ETG_OUTCOME_FALSIFIED } 181 if pathology == NX_PERF_PATH_THROUGHPUT_CLIFF { outcome = NX_ETG_OUTCOME_FALSIFIED } 182 if pathology == NX_PERF_PATH_SECOND_CLASS_RESOURCE { outcome = NX_ETG_OUTCOME_FALSIFIED } 183 if pathology == NX_PERF_PATH_VENDOR_PAYWALL_HONORED { outcome = NX_ETG_OUTCOME_PAYWALLED_BUT_RESPONSIVE } 184 if pathology == NX_PERF_PATH_SINGLE_ARCH_OVERFIT { outcome = NX_ETG_OUTCOME_FALSIFIED } 185 186 // Emit attestation: claim_value = upper bound; measurement_value 187 // = pathology id (audit-replayable). 188 let rc: i64 = nx_etg_entry_init( 189 entry, 190 silicon_serial, 191 probe_kind, 192 NX_ETG_CLAIM_VENDOR_DOC, 193 upper_ns, 194 pathology, 195 outcome, 196 selector_version, 197 timestamp_q14 198 ) 199 if rc != 0 { return rc } 200 201 result.n_measured = n_samples 202 result.median_ns = median 203 result.p99_ns = p99 204 result.min_ns = min_v 205 result.max_ns = max_v 206 result.in_band = in_band 207 result.pathology = pathology 208 result.pathology_name = nx_perf_path_name(pathology) 209 result.attestation_hash = entry.attestation_hash 210 211 return 0 212}