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}