perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer - #442

Merged
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf
Jul 30, 2026
Merged

perf(rust-kernel): Intern-assigned uids, symbolic Nat offsets, environment-machine WHNF reducer#442
samuelburnham merged 26 commits into
mainfrom
sb/kernel-perf

Conversation

@samuelburnham

Copy link
Copy Markdown
Member

This pull request implements Rust-kernel and ixon optimizations for the Zisk guest, measured against the base #411 as deterministic guest cycle counts (ziskemu -m) over dumped shard inputs (zisk/scripts/bench-cycles.sh), with every counted run's committed failures publics word verified zero.

Key Results

  • Int16.instRxcHasSize_eq: 5.70 B → 42.0 M guest steps (135.6×); Int32/Int64 variants confirmed at the same magnitude (~42 M) — in-circuit cost is now integer-width-independent
  • Cycle suite total: 17.53 B → 5.77 B steps (3.04×, −67.1%)
  • Environment-machine WHNF (final two kernel commits): −19.3% suite net; Vector.extract_append._proof_1 −32.4%; the Init Array/Vector Extract proof family −22% to −33% each (five multi-billion-step constants)
  • Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual (28.35 B steps, the most expensive constant measured in Init+Std): previously crashed the 512 MB guest (OOM-class null read) → now completes as a valid kernel pass — lazy closures cut peak RAM, not just cycles
  • Kernel hardened against adversarial inputs: term identity moved off per-node content hashing with the threat model documented (docs/kernel_identity.md), blob bytes verified at load in all deserializers
inputbase (#411)this PRΔspeedup
_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq5,697,166,20042,012,168−99.3%135.6×
_private.Init.Data.Vector.Extract.0.Vector.extract_append._proof_17,690,887,2113,344,459,375−56.5%2.3×
List.mergesort synthetic env4,005,320,3472,290,310,593−42.8%1.7×
Nat.add_comm18,690,81511,532,048−38.3%1.6×
Array.binSearchAux._unary95,800,41162,862,965−34.4%1.5×
Nat.gcd_comm6,669,8215,550,752−16.8%1.2×
Batteries.RBMap13,940,41212,321,092−11.6%1.1×
String.append4,560,3044,070,450−10.7%1.1×
total17,533,035,5215,773,119,443−67.1%3.04×

Fifteen Commits (oldest first)

  1. bench: guest cycle harness + native single-constant check

    • bench-cycles.sh suite over dumped guest stdins with failures-word validation; check_one example mirrors the guest's reuse-mode check natively
  2. kernel: keep symbolic Nat offsets compact (whnf stuck + offset def-eq)

    • Nat.add x lit / Nat.div|mod x k stay stuck as compact offsets instead of materializing succ^n(x) chains or the division algorithm; bulk offset def-eq decides offset pairs directly
    • The Int16.instRxcHasSize_eq collapse (5.70 B → 56 M) and the UTF-8-codec-class fix
  3. kernel: intern-assigned uids replace per-node blake3 content hashing

    • Term identity becomes intern-table-assigned sequential u64s; shallow structural keys for hash-consing; blake3 stays only at the Ixon boundary (content addresses, Merkle roots, proof-carrying-code claims)
    • The broadest single win: −30–36% on every reduction-heavy input
  4. kernel: memoized prim-family dispatch in the WHNF/def-eq reduction loops

    • Constant heads classified once per address (Native/BitVec/Nat/Decidable/Str); at most one family recognizer runs per iteration instead of the five-probe gauntlet
  5. ixon: defer per-constant address verification to first materialization

    • Constants verify on first get(); blob bytes still verified eagerly at load
  6. bench: add Int32/Int64 instRxcHasSize_eq to the cycle suite

  7. docs: kernel uid identity vs Ixon content addressing

    • Two-layer identity model and why uid collisions are not an attack surface (uids are assigned, never computed from input)
  8. kernel: fix PrimFamily visibility/qualification warnings

  9. kernel: port jcb/fixes H-15 whnf probe pre-filter + H-12 nat output caps

    • Allocation-free transient-nat spine probe ahead of the cache lookup; caps on Nat primitive output sizes
  10. kernel+ixon: harden term identity against adversarial inputs

    • Blob bytes verified against their address at load in all three deserializers; structural equality audited against the adversarial model
  11. kernel: privatize uid-accepting constructors; document cross-shard uid story

  12. docs: design for the environment-machine WHNF port

    • Full design for the Krivine-style machine (ported from the proven IxVM implementation), including the exit-to-outer-loop contract and the known regression class
  13. kernel: environment-machine WHNF (Phase A — lazy substitution on the beta path)

    • whnf_core's App arm enters a closure machine when a beta fires: beta/zeta are O(1) environment pushes; substitution materializes only at machine exits (clo_subst readback), so work is proportional to what the reduction consumes
    • Every exit re-enters the existing loop: ambient zeta, iota, prim dispatch, cheap-mode def-eq flags, and all caches stay byte-identical
  14. kernel: closure-iota at the machine's recursor exit (Phase B)

    • Recursor spines consumed lazily: only the major premise materializes; params/motives/minors and post-major args ride through as closures, so unselected minors (dropped match/Decidable branches) are never substituted and never read back
    • K recursors, literal majors, and struct-eta deliberately miss to the unchanged plain path, preserving the Nat transient-work and linear-rec/offset shortcuts exactly
  15. docs: env-machine WHNF design is implemented (Phases A+B)

@samuelburnham
samuelburnhamforce-pushed the kernel-riscv branch 7 times, most recently from 582d40b to 61cb1bdCompareJune 29, 2026 21:07
Base automatically changed from kernel-riscv to mainJune 30, 2026 13:41
@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from 5b0cf31 to 06e1a1dCompareJuly 24, 2026 01:32
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Some benchmark jobs failed — results may be partial.

!benchmark — main vs 06e1a1d

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 3312c3f (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd10.963 s17.971 s+63.9% (1.64× slower) ⚠️8.12K4.95K-39.0% (1.64× slower) ⚠️1.88 GiB1.81 GiB-4.1% 🟢
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.387 s4.896 s-23.3% (1.30× faster) 🟢887.0501.16K+30.5% (1.30× faster) 🟢1.88 GiB1.75 GiB-6.7% (1.07× smaller) 🟢
Array.extract_append1.017 s769.2 ms-24.4% (1.32× faster) 🟢1.52K2.01K+32.2% (1.32× faster) 🟢1.23 GiB1.38 GiB+11.8% (1.12× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append529.5 ms532.6 ms+0.6%5.09K5.06K-0.6%1.23 GiB1.12 GiB-8.7% (1.10× smaller) 🟢
Vector.extract_append._proof_21.012 s513.8 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.1% (1.97× faster) 🟢1.42 GiB1.51 GiB+6.5% (1.07× larger) ⚠️
Char.ofOrdinal_le_of_le774.1 ms276.9 ms-64.2% (2.80× faster) 🟢3.43K9.60K+179.6% (2.80× faster) 🟢1.03 GiB925.72 MiB-12.0% (1.14× smaller) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq1.015 s267.3 ms-73.7% (3.80× faster) 🟢1.79K6.80K+279.6% (3.80× faster) 🟢1.45 GiB1.53 GiB+5.9% (1.06× larger) ⚠️
String.split264.2 ms265.2 ms+0.4%6.71K6.68K-0.4%1.19 GiB1.29 GiB+8.4% (1.08× larger) ⚠️
List.mergeSort261.6 ms262.7 ms+0.4%5.56K5.53K-0.4%932.45 MiB975.80 MiB+4.6% ⚠️
Nat.gcd_comm254.2 ms255.0 ms+0.3%1.53K1.53K-0.3%809.72 MiB848.80 MiB+4.8% ⚠️
Vector.append255.2 ms255.0 ms-0.1%1.95K1.95K+0.1%808.94 MiB760.88 MiB-5.9% (1.06× smaller) 🟢
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.12 GiB1.19 GiB+6.7% (1.07× larger) ⚠️
Nat.sub_le_of_le_add253.1 ms252.7 ms-0.2%671.680672.790+0.2%586.75 MiB572.40 MiB-2.4%
Nat.add_comm252.1 ms252.6 ms+0.2%166.590166.280-0.2%474.31 MiB448.05 MiB-5.5% (1.06× smaller) 🟢
Int.gcd252.6 ms252.6 ms+0.0%823.580823.520-0.0%650.78 MiB650.53 MiB-0.0%

15 env/constants · 8 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 3312c3f (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.805 sn/an/a65n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.434 sn/an/a94n/an/a53.56 GiBn/an/a12.90Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.808 sn/an/a56n/an/a70.50 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.974 sn/an/a112n/an/a52.95 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.387 sn/an/a83n/an/a70.52 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.493 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.234 sn/an/a135n/an/a52.76 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.477 sn/an/a222n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.683 sn/an/a245n/an/a52.08 GiBn/an/a742.79Mn/an/a413n/an/a2n/a
String.appendn/a820.6 msn/an/a409n/an/a55.34 GiBn/an/a360.74Mn/an/a336n/an/a1n/a
Int.gcdn/a566.4 msn/an/a401n/an/a55.19 GiBn/an/a245.33Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a527.5 msn/an/a356n/an/a55.17 GiBn/an/a222.43Mn/an/a188n/an/a1n/a
Nat.add_commn/a110.0 msn/an/a445n/an/a55.20 GiBn/an/a31.51Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs cbbad89

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 7d99a71 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.461 s16.468 s+74.1% (1.74× slower) ⚠️9.41K5.41K-42.5% (1.74× slower) ⚠️1.90 GiB2.00 GiB+5.3% (1.05× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.390 s4.641 s-27.4% (1.38× faster) 🟢886.7001.22K+37.7% (1.38× faster) 🟢1.92 GiB1.87 GiB-2.4%
Array.extract_append1.016 s767.5 ms-24.5% (1.32× faster) 🟢1.52K2.02K+32.4% (1.32× faster) 🟢1.25 GiB1.53 GiB+23.1% (1.23× larger) ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.2 ms531.4 ms+0.6%5.11K5.08K-0.6%1.09 GiB1.16 GiB+6.2% (1.06× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.45 GiB1.43 GiB-1.1%
Char.ofOrdinal_le_of_le773.0 ms275.5 ms-64.4% (2.81× faster) 🟢3.44K9.65K+180.5% (2.81× faster) 🟢982.46 MiB1.28 GiB+33.4% (1.33× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.2 ms265.3 ms-65.3% (2.88× faster) 🟢2.38K6.85K+188.0% (2.88× faster) 🟢1.37 GiB1.28 GiB-6.6% (1.07× smaller) 🟢
String.split263.3 ms264.5 ms+0.5%6.73K6.70K-0.5%1.24 GiB1.26 GiB+2.0%
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%966.89 MiB1.04 GiB+9.7% (1.10× larger) ⚠️
Vector.append254.2 ms255.2 ms+0.4%1.96K1.95K-0.4%701.89 MiB841.38 MiB+19.9% (1.20× larger) ⚠️
Nat.gcd_comm253.9 ms254.2 ms+0.1%1.54K1.53K-0.1%881.78 MiB841.38 MiB-4.6% 🟢
String.append253.0 ms253.0 ms+0.0%1.21K1.21K-0.0%1.15 GiB1.23 GiB+7.1% (1.07× larger) ⚠️
Int.gcd252.4 ms252.7 ms+0.1%824.160823.060-0.1%729.70 MiB679.06 MiB-6.9% (1.07× smaller) 🟢
Nat.sub_le_of_le_add252.5 ms252.4 ms-0.0%673.370673.500+0.0%648.44 MiB594.73 MiB-8.3% (1.09× smaller) 🟢
Nat.add_comm252.0 ms252.0 ms-0.0%166.680166.700+0.0%509.85 MiB462.18 MiB-9.3% (1.10× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 7d99a71 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a42.342 sn/an/a66n/an/a53.80 GiBn/an/a18.72Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a29.300 sn/an/a95n/an/a53.43 GiBn/an/a12.92Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.328 sn/an/a57n/an/a70.54 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.641 sn/an/a114n/an/a53.01 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a16.227 sn/an/a84n/an/a70.59 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.494 sn/an/a129n/an/a52.97 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a11.006 sn/an/a138n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.414 sn/an/a228n/an/a52.43 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.660 sn/an/a249n/an/a52.09 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a819.6 msn/an/a410n/an/a55.34 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a553.3 msn/an/a410n/an/a55.19 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a493.2 msn/an/a381n/an/a55.16 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a115.2 msn/an/a425n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

@samuelburnham
samuelburnhamforce-pushed the sb/kernel-perf branch 2 times, most recently from a77f444 to 64bc041CompareJuly 24, 2026 17:08
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk ooc

@argument-ci-bot

argument-ci-botBot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 64bc041

backends: zisk ooc · envs: InitStd · set: primary · shard: 0

ooc · InitStd — main from: base run @ 6e29ac9 (not on bencher)

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.460 s16.967 s+79.4% (1.79× slower) ⚠️9.41K5.25K-44.2% (1.79× slower) ⚠️1.82 GiB1.98 GiB+8.9% (1.09× larger) ⚠️
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.383 s4.643 s-27.3% (1.37× faster) 🟢887.6501.22K+37.5% (1.37× faster) 🟢2.04 GiB1.81 GiB-11.2% (1.13× smaller) 🟢
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.4 ms531.8 ms+0.6%5.10K5.07K-0.6%1.20 GiB1.16 GiB-2.8%
Array.extract_append1.016 s517.6 ms-49.1% (1.96× faster) 🟢1.52K2.99K+96.4% (1.96× faster) 🟢1.19 GiB1.48 GiB+24.0% (1.24× larger) ⚠️
Vector.extract_append._proof_21.012 s512.6 ms-49.3% (1.97× faster) 🟢1.29K2.55K+97.4% (1.97× faster) 🟢1.52 GiB1.44 GiB-5.2% (1.05× smaller) 🟢
Char.ofOrdinal_le_of_le773.1 ms276.6 ms-64.2% (2.79× faster) 🟢3.44K9.61K+179.5% (2.79× faster) 🟢1.12 GiB1.55 GiB+38.6% (1.39× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.1 ms265.5 ms-65.3% (2.88× faster) 🟢2.38K6.85K+187.8% (2.88× faster) 🟢1.46 GiB1.55 GiB+5.9% (1.06× larger) ⚠️
String.split263.7 ms264.9 ms+0.4%6.72K6.69K-0.4%1.30 GiB1.24 GiB-4.8% (1.05× smaller) 🟢
List.mergeSort261.0 ms262.0 ms+0.4%5.57K5.55K-0.4%1.02 GiB1003.31 MiB-3.6% 🟢
Vector.append255.6 ms255.4 ms-0.1%1.95K1.95K+0.1%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
Nat.gcd_comm253.8 ms254.3 ms+0.2%1.54K1.53K-0.2%885.11 MiB930.82 MiB+5.2% (1.05× larger) ⚠️
String.append253.0 ms253.1 ms+0.0%1.21K1.21K-0.0%1.10 GiB1.19 GiB+7.8% (1.08× larger) ⚠️
Int.gcd252.6 ms252.7 ms+0.0%823.410823.130-0.0%720.55 MiB724.12 MiB+0.5%
Nat.sub_le_of_le_add252.6 ms252.6 ms+0.0%673.090673.040-0.0%628.77 MiB609.14 MiB-3.1% 🟢
Nat.add_comm252.0 ms252.1 ms+0.0%166.660166.630-0.0%490.19 MiB456.57 MiB-6.9% (1.07× smaller) 🟢

15 env/constants · 7 with regressions · 9 with improvements (|Δ| > 3.0% on any metric).

zisk · InitStd — main from: base run @ 6e29ac9 (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_appendn/a41.586 sn/an/a67n/an/a53.77 GiBn/an/a18.69Bn/an/a2,785n/an/a33n/a
Char.ofOrdinal_le_of_len/a28.665 sn/an/a97n/an/a53.59 GiBn/an/a12.95Bn/an/a2,776n/an/a22n/a
Array.extract_appendn/a28.108 sn/an/a58n/an/a70.63 GiBn/an/a12.48Bn/an/a1,627n/an/a13n/a
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eqn/a16.340 sn/an/a116n/an/a53.00 GiBn/an/a7.35Bn/an/a1,896n/an/a13n/a
Vector.extract_append._proof_2n/a15.866 sn/an/a86n/an/a70.61 GiBn/an/a7.03Bn/an/a1,367n/an/a8n/a
String.splitn/a14.243 sn/an/a131n/an/a53.04 GiBn/an/a6.42Bn/an/a1,867n/an/a11n/a
List.mergeSortn/a10.813 sn/an/a140n/an/a52.79 GiBn/an/a4.91Bn/an/a1,517n/an/a9n/a
Vector.appendn/a2.397 sn/an/a229n/an/a52.42 GiBn/an/a1.10Bn/an/a550n/an/a3n/a
Nat.gcd_commn/a1.643 sn/an/a251n/an/a52.08 GiBn/an/a743.01Mn/an/a413n/an/a2n/a
String.appendn/a801.3 msn/an/a419n/an/a55.35 GiBn/an/a360.85Mn/an/a336n/an/a1n/a
Int.gcdn/a534.9 msn/an/a424n/an/a55.18 GiBn/an/a245.40Mn/an/a227n/an/a1n/a
Nat.sub_le_of_le_addn/a495.4 msn/an/a379n/an/a55.18 GiBn/an/a222.50Mn/an/a188n/an/a1n/a
Nat.add_commn/a104.5 msn/an/a469n/an/a55.23 GiBn/an/a31.53Mn/an/a49n/an/a1n/a

13 constants · 0 with regressions · 0 with improvements (|Δ| > 3.0% on any metric).

⚠️ no main-side results (base run failed — see the workflow logs).

Workflow logs

Rebase of the sb/kernel-perf kernel stack onto main (the early
workspace/backend/sharding commits of this branch were superseded by
their evolved forms merged in #411/#503; this carries only the novel
kernel work, reconciled with main's #473 declared-flag removal and
is_rec_cache):
- intern-assigned uids replace per-node blake3 content hashing: KExpr/
KUniv identity is a never-reused process-global u64; InternTable keys
on shallow structural keys (variant tag + child uids + payload);
cache keys cannot alias across intern-table clears (a stale key can
only miss). ~20% of guest cycles on reduction-heavy constants came
from content hashing (app_hash 22-33% cumulative). Design + collision
analysis in docs/kernel_identity.md.
- adversarial hardening of the uid design: fresh_uid aborts on counter
exhaustion; literal structural-equality arms compare values as well
as blob addresses; uid-accepting constructors privatized so a
caller-supplied uid can never enter a node.
- environment-machine WHNF (design in docs/env_machine_whnf.md):
Phase A — whnf_core's App arm enters a Krivine-style machine when a
beta fires; beta/zeta are O(1) environment pushes and substitution
materializes only at machine exits (clo_subst readback), so a beta
chain ending in another beta never materializes intermediate bodies.
Phase B — closure-iota at the machine's recursor exit: only the major
premise materializes on the main ctor-rule path; the rule RHS
re-enters the machine with original closures, so unselected minors
(dropped match/Decidable branches, the UTF-8 codec class) are never
substituted and never read back.
- memoized prim-family dispatch in the WHNF/def-eq reduction loops:
classify each head once per iteration via an allocation-free
app-chain walk + per-address memo (KEnv::prim_family_cache) instead
of probing all five primitive recognizers per iteration.
- compact symbolic Nat offsets: Nat.add base (Lit n) / Nat.div/mod
base (Lit k) stay stuck in compact form (each keeps its own head, so
offset def-eq cannot equate /- and +-derived forms); linear-rec
collapse; offset-aware def-eq.
- H-15 whnf probe pre-filter (allocation-free spine_head_and_len before
the transient-nat probes) and H-12 output-size caps on native Nat
arithmetic.
- suffix-aware CtxAddr keys for the is_prop / nat_succ_stuck caches;
NatSuccMode::Stuck whnf cache (proves
ByteArray.utf8DecodeChar?_utf8EncodeChar_append).
- ixon: per-constant address verification deferred to first
materialization (LazyConstant::get checks pending_addr): constants
shipped in a closure but never forced by the typechecker are never
hashed; everything the kernel certifies is still verified when it is
forced. Guest cycles: rbmap -9.5%, natgcdcomm -6.4%,
stringappend -4.2%.
Standalone cargo examples over a .ixe env, bypassing the Lean/FFI
layer, updated to main's steps-based shard cost model
(block_step_cost / partition_for_cycle_cap / cycle_cap_for_ram):
- shard_plan: profile → partition → .ixes manifest, with store-aware
planning (--store-dir drops work items whose targets the proof store
already covers, and excludes covered blocks from the partition
hypergraph — a novel→covered edge is an assumption discharged at
aggregation, not a cut to minimize); sizes N from machine RAM by
default.
- perf_check / check_one: native rerun of the guest check_const loop so
IX_* perf-counter instrumentation can target a single expensive
constant without re-checking its env.
- heaviest_block / block_reduce_histo / shard_names / manifest_info:
profiling forensics over blocks and manifests.
- zisk/scripts: prove-batch (sequential shard proving), mem-guard
(MemAvailable watchdog that kills zisk-host before the OOM killer
wedges the box), bench-cycles, mergesort-250k repro; reference logs.
- sp1/scripts/prove-ix.sh + GPU logs (dev-only; runs with
WITHOUT_VK_VERIFICATION=1).
- Lean side: bench-compile-init lake exe (imports Init, empty main).
…pinning)
The aggregate proof was weaker than "these subjects are well-typed":
- The agg guest never read a child's committed failures word (slot 10)
and hard-committed 0 for its own, so aggregation ERASED the failure
bit — a kernel-rejected constant could appear under a failures=0 root,
with only host-side courtesy checks in the way. Every child's failures
word is now asserted 0 in-circuit.
- vk pinning was not transitive: a child that is itself an aggregate was
pinned only by its program vk (the shared AGG vk); its own allowed-vk
set was never inspected. An agg-of-1 built against a rogue allowed set
(wrapping an arbitrary program's "proof" with forged publics) would
fold under an honest-looking root. The agg guest now requires every
aggregate child (allowed-set index ≥ 1, by the new positional
convention: index 0 = leaf vk, the rest agg vks) to commit THIS
instance's vks id — the allowed set is uniform down the tree, so the
pin is recursive. The convention's ordering is bound by the committed
id hash, which external verifiers already check.
- The host derived the allowed set FROM the untrusted child proofs
(distinct_vks), so any proof admitted its own program, and a stale
store folded silently under its old vk. The allowed set is now
[shard_vk, agg_vk] derived from the embedded ELFs (GuestProgram::vk
after ROM setup); freshly produced proofs are asserted to match;
stored proofs with a different vk are skipped (re-proven); and the
root's committed vks id is checked against — and printed for —
external verifiers.
- A manifest bisection tree whose leaf set differs from the shard id set
silently dropped proven leaves from the fold while the pre-aggregation
coverage check (counting proofs PRODUCED, not folded) still passed.
ShardManifest::from_bytes now rejects such trees, and the host
additionally checks post-fold that every env target is in the root's
actual subject set.
@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk

@argument-ci-bot

argument-ci-botBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs d392646

backends: zisk · envs: InitStd · set: primary · shard: 0

zisk · InitStd — main from: base run @ 7ff054b (not on bencher)

constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.7s42.029 s-36.0% (1.56× faster) 🟢4266+57.1% (1.57× faster) 🟢70.51 GiB53.59 GiB-24.0% (1.32× smaller) 🟢33.86B18.67B-44.8% (1.81× fewer) 🟢2,7852,785+0.0%3433-2.9%
Array.extract_append48.360 s29.011 s-40.0% (1.67× faster) 🟢3456+64.7% (1.65× faster) 🟢113.14 GiB70.54 GiB-37.7% (1.60× smaller) 🟢23.88B12.48B-47.7% (1.91× fewer) 🟢1,6271,627+0.0%1313+0.0%
Char.ofOrdinal_le_of_le52.117 s28.884 s-44.6% (1.80× faster) 🟢5396+81.1% (1.81× faster) 🟢82.84 GiB53.47 GiB-35.5% (1.55× smaller) 🟢26.70B12.94B-51.5% (2.06× fewer) 🟢2,7762,776+0.0%2622-15.4% (1.18× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.894 s16.539 s-52.6% (2.11× faster) 🟢54115+113.0% (2.13× faster) 🟢99.26 GiB53.05 GiB-46.6% (1.87× smaller) 🟢17.71B7.35B-58.5% (2.41× fewer) 🟢1,8961,896+0.0%1513-13.3% (1.15× fewer) 🟢
Vector.extract_append._proof_227.931 s16.276 s-41.7% (1.72× faster) 🟢4984+71.4% (1.71× faster) 🟢113.07 GiB70.58 GiB-37.6% (1.60× smaller) 🟢13.62B7.03B-48.4% (1.94× fewer) 🟢1,3671,367+0.0%88+0.0%
String.split19.746 s14.465 s-26.7% (1.37× faster) 🟢95129+35.8% (1.36× faster) 🟢52.92 GiB53.04 GiB+0.2%10.37B6.42B-38.0% (1.61× fewer) 🟢1,8671,867+0.0%1111+0.0%
List.mergeSort15.633 s11.043 s-29.4% (1.42× faster) 🟢97137+41.2% (1.41× faster) 🟢52.78 GiB52.82 GiB+0.1%8.19B4.91B-40.1% (1.67× fewer) 🟢1,5171,517+0.0%99+0.0%
Vector.append3.287 s2.432 s-26.0% (1.35× faster) 🟢167226+35.3% (1.35× faster) 🟢52.42 GiB52.43 GiB+0.0%1.75B1.10B-37.2% (1.59× fewer) 🟢550550+0.0%33+0.0%
Nat.gcd_comm2.326 s1.698 s-27.0% (1.37× faster) 🟢178243+36.5% (1.37× faster) 🟢52.14 GiB52.09 GiB-0.1%1.21B743.05M-38.6% (1.63× fewer) 🟢413413+0.0%22+0.0%
String.append1.142 s866.6 ms-24.1% (1.32× faster) 🟢294388+32.0% (1.32× faster) 🟢55.36 GiB55.35 GiB-0.0%586.26M360.87M-38.4% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd800.8 ms557.5 ms-30.4% (1.44× faster) 🟢283407+43.8% (1.44× faster) 🟢55.23 GiB55.19 GiB-0.1%403.39M245.42M-39.2% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add713.1 ms512.0 ms-28.2% (1.39× faster) 🟢264367+39.0% (1.39× faster) 🟢55.20 GiB55.17 GiB-0.1%368.19M222.51M-39.6% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm140.0 ms111.5 ms-20.4% (1.26× faster) 🟢350439+25.4% (1.25× faster) 🟢55.21 GiB55.22 GiB+0.0%52.60M31.54M-40.0% (1.67× fewer) 🟢4949+0.0%11+0.0%

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc BENCH_ENVS=Mathlib fresh

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark ooc fresh

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: Mathlib · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · Mathlib — main from: base run @ 7ff054b (fresh — bencher bypassed)

3 env/constants · 1 with regressions · 1 with improvements (|Δ| > 3.0% on any metric).

env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
Mathlib3m 6.3s2m 18.6s-25.6% (1.34× faster) 🟢3.44K4.62K+34.4% (1.34× faster) 🟢9.06 GiB10.58 GiB+16.7% (1.17× larger) ⚠️
Multiset.sort278.2 ms278.1 ms-0.0%5.82K5.82K+0.0%3.46 GiB3.51 GiB+1.3%
Nat.factorial260.7 ms260.3 ms-0.2%126.580126.790+0.2%3.05 GiB3.02 GiB-0.9%

Workflow logs

@argument-ci-bot

argument-ci-botBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: ooc · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

ooc · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

15 env/constants · 6 with regressions · 7 with improvements (|Δ| > 3.0% on any metric).

comparison table (15 env/constants)
env/constantcheck-time (main)check-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%
InitStd9.708 s6.225 s-35.9% (1.56× faster) 🟢9.17K14.30K+56.0% (1.56× faster) 🟢1.88 GiB1.93 GiB+2.7%
Std.Tactic.BVDecide.BVExpr.bitblast.goCache_Inv_of_Inv._mutual6.136 s2.882 s-53.0% (2.13× faster) 🟢923.3901.97K+112.9% (2.13× faster) 🟢1.98 GiB1.99 GiB+0.6%
Array.extract_append1.016 s516.3 ms-49.2% (1.97× faster) 🟢1.52K3.00K+96.9% (1.97× faster) 🟢1.20 GiB1.09 GiB-8.7% (1.09× smaller) 🟢
Vector.extract_append._proof_21.012 s511.8 ms-49.4% (1.98× faster) 🟢1.29K2.56K+97.8% (1.98× faster) 🟢1.44 GiB1.51 GiB+4.9% ⚠️
ByteArray.utf8DecodeChar?_utf8EncodeChar_append528.7 ms278.5 ms-47.3% (1.90× faster) 🟢5.10K9.68K+89.8% (1.90× faster) 🟢1.08 GiB1.15 GiB+6.4% (1.06× larger) ⚠️
Char.ofOrdinal_le_of_le773.4 ms273.0 ms-64.7% (2.83× faster) 🟢3.44K9.74K+183.3% (2.83× faster) 🟢1.05 GiB1.52 GiB+44.7% (1.45× larger) ⚠️
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq764.4 ms264.3 ms-65.4% (2.89× faster) 🟢2.38K6.88K+189.3% (2.89× faster) 🟢1.28 GiB1.34 GiB+4.3% ⚠️
String.split263.6 ms263.8 ms+0.1%6.72K6.72K-0.1%1.27 GiB1.25 GiB-1.4%
List.mergeSort261.5 ms261.1 ms-0.2%5.56K5.57K+0.2%960.00 MiB1022.73 MiB+6.5% (1.07× larger) ⚠️
Vector.append254.8 ms255.1 ms+0.1%1.95K1.95K-0.1%865.98 MiB875.68 MiB+1.1%
Nat.gcd_comm254.0 ms254.1 ms+0.0%1.54K1.54K-0.0%865.98 MiB875.68 MiB+1.1%
String.append252.9 ms252.9 ms-0.0%1.21K1.21K+0.0%970.33 MiB1.00 GiB+6.1% (1.06× larger) ⚠️
Nat.sub_le_of_le_add252.6 ms252.7 ms+0.0%672.970672.760-0.0%609.28 MiB604.96 MiB-0.7%
Int.gcd252.4 ms252.4 ms+0.0%824.010823.960-0.0%691.48 MiB691.42 MiB-0.0%
Nat.add_comm252.3 ms252.2 ms-0.0%166.490166.570+0.0%472.58 MiB466.16 MiB-1.4%

Workflow logs

@samuelburnham

Copy link
Copy Markdown
MemberAuthor

!benchmark zisk fresh

@argument-ci-bot

argument-ci-botBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

!benchmark — main vs 7733556

backends: zisk · envs: InitStd · set: primary · shard: 0 · baseline: fresh (base-SHA run, bencher bypassed)

zisk · InitStd — main from: base run @ 7ff054b (fresh — bencher bypassed)

13 constants · 0 with regressions · 13 with improvements (|Δ| > 3.0% on any metric).

comparison table (13 constants)
constantexecute-time (main)execute-time (PR)Δ%throughput (const/s) (main)throughput (const/s) (PR)Δ%peak-ram (main)peak-ram (PR)Δ%cycles (main)cycles (PR)Δ%constants (main)constants (PR)Δ%shards (main)shards (PR)Δ%
ByteArray.utf8DecodeChar?_utf8EncodeChar_append1m 5.8s38.461 s-41.6% (1.71× faster) 🟢4272+71.4% (1.71× faster) 🟢70.55 GiB55.14 GiB-21.8% (1.28× smaller) 🟢33.86B16.78B-50.4% (2.02× fewer) 🟢2,7852,785+0.0%3413-61.8% (2.62× fewer) 🟢
Array.extract_append48.878 s27.548 s-43.6% (1.77× faster) 🟢3359+78.8% (1.79× faster) 🟢113.21 GiB70.87 GiB-37.4% (1.60× smaller) 🟢23.88B11.86B-50.3% (2.01× fewer) 🟢1,6271,627+0.0%137-46.2% (1.86× fewer) 🟢
Char.ofOrdinal_le_of_le53.019 s27.056 s-49.0% (1.96× faster) 🟢52103+98.1% (1.98× faster) 🟢82.85 GiB54.34 GiB-34.4% (1.52× smaller) 🟢26.70B11.76B-56.0% (2.27× fewer) 🟢2,7762,776+0.0%269-65.4% (2.89× fewer) 🟢
Vector.extract_append._proof_227.655 s16.075 s-41.9% (1.72× faster) 🟢4985+73.5% (1.73× faster) 🟢113.17 GiB70.60 GiB-37.6% (1.60× smaller) 🟢13.62B6.88B-49.5% (1.98× fewer) 🟢1,3671,367+0.0%85-37.5% (1.60× fewer) 🟢
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq34.972 s15.163 s-56.6% (2.31× faster) 🟢54125+131.5% (2.31× faster) 🟢99.17 GiB53.85 GiB-45.7% (1.84× smaller) 🟢17.71B6.52B-63.2% (2.72× fewer) 🟢1,8961,896+0.0%156-60.0% (2.50× fewer) 🟢
String.split19.656 s13.406 s-31.8% (1.47× faster) 🟢95139+46.3% (1.46× faster) 🟢52.88 GiB53.80 GiB+1.7%10.37B5.88B-43.3% (1.76× fewer) 🟢1,8671,867+0.0%115-54.5% (2.20× fewer) 🟢
List.mergeSort15.685 s10.678 s-31.9% (1.47× faster) 🟢97142+46.4% (1.46× faster) 🟢52.77 GiB53.73 GiB+1.8%8.19B4.53B-44.6% (1.81× fewer) 🟢1,5171,517+0.0%94-55.6% (2.25× fewer) 🟢
Vector.append3.273 s2.233 s-31.8% (1.47× faster) 🟢168246+46.4% (1.46× faster) 🟢52.42 GiB52.62 GiB+0.4%1.75B1.00B-42.7% (1.74× fewer) 🟢550550+0.0%31-66.7% (3.00× fewer) 🟢
Nat.gcd_comm2.299 s1.633 s-29.0% (1.41× faster) 🟢180253+40.6% (1.41× faster) 🟢52.14 GiB52.41 GiB+0.5%1.21B689.37M-43.0% (1.76× fewer) 🟢413413+0.0%21-50.0% (2.00× fewer) 🟢
String.append1.115 s860.5 ms-22.8% (1.30× faster) 🟢301390+29.6% (1.30× faster) 🟢55.35 GiB55.37 GiB+0.0%586.26M362.58M-38.2% (1.62× fewer) 🟢336336+0.0%11+0.0%
Int.gcd770.9 ms572.7 ms-25.7% (1.35× faster) 🟢294396+34.7% (1.35× faster) 🟢55.21 GiB55.20 GiB-0.0%403.39M246.57M-38.9% (1.64× fewer) 🟢227227+0.0%11+0.0%
Nat.sub_le_of_le_add704.1 ms509.0 ms-27.7% (1.38× faster) 🟢267369+38.2% (1.38× faster) 🟢55.20 GiB55.18 GiB-0.0%368.19M223.57M-39.3% (1.65× fewer) 🟢188188+0.0%11+0.0%
Nat.add_comm144.0 ms104.5 ms-27.5% (1.38× faster) 🟢340469+37.9% (1.38× faster) 🟢55.21 GiB55.21 GiB-0.0%52.60M31.68M-39.8% (1.66× fewer) 🟢4949+0.0%11+0.0%

Workflow logs

johnchandlerburnham
johnchandlerburnham previously approved these changes Jul 30, 2026
- Untrack sp1/zisk benchmark logs and scripts
- Remove dev-tooling examples from ix-kernel: examples are for showing
users how to use the crate; the shard-planning and perf binaries
live on in git history
- Remove the env-machine design doc; the as-built machine is
documented at the code (whnf.rs machine_whnf, subst.rs Clo)
@samuelburnham
samuelburnham merged commit 6989997 into mainJul 30, 2026
10 checks passed
@samuelburnham
samuelburnham deleted the sb/kernel-perf branch July 30, 2026 16:05
samuelburnham added a commit that referenced this pull request Aug 4, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
samuelburnham added a commit that referenced this pull request Aug 8, 2026
…acking
Port of sb/measured-ingress's planning layer onto the addr-first kernel
(#529), reworked for its lazy fault-in semantics.
Profiling (.ixprof v3): the recording kernel's try_get_const consults are
drained per constant into a touch graph — the measured set a lazy checker
faults in — persisted as a presence-flagged CSR section alongside a new
block-level reference graph and a subst_unique counter (splitmix64-keyed
dedup of substitution work items: the post-memoization volume a memoizing
executor pays). Both graph sections are optional, so older readers'
formats stay decodable by version gate alone.
Planner: partition_for_aiur_ram bin-packs to a host-RAM cap with
faulted-set byte accounting — under #529 the witness always ships the
full closure, but only faulted bytes cost ingress trace rows, so a
shard's byte feature is owned ∪ touched(owned) (full reference closure
as the over-approximating fallback when no touch graph was recorded).
The stub/promotion machinery of the original branch is dropped entirely:
lazy fault-in computes at run time exactly the set the stubs predicted,
with no replay divergence and no repair ladder, and the manifest format
stays byte-identical with main (owned-only).
Cost models: nlogn(x) = x·log2(x+2) feature form matching Aiur's
width·height·log2(height) FFT structure; prove/execute time and RAM
coefficients carried over from the pre-#529 aiur bench-suite fits.
They are placeholders pending a refit against this kernel — the circuit
shrank (deleted positional machinery), the byte feature narrowed to the
faulted set, and the recording counters moved under #442 — with
provenance noted at the definitions. The costs sidecar
(<out>.costs.csv) persists per-shard features incl. subst_unique and
nat_arith so the refit has its corpus.
CLI: ix shard --backend aiur --max-ram G; ix profile --backend/--top
(per-metric block leaderboards with display names) and ix profile sweep
(env-wide closure cost sweep: per-root feature CSV + feasibility,
min-root-per-hot-block, and diversity reports).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@samuelburnham@johnchandlerburnham@arthurpaulino