From 565ea3789608a054cc9cbec3b9845b8064600aca Mon Sep 17 00:00:00 2001 From: samuelburnham <45365069+samuelburnham@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:48:33 +0000 Subject: [PATCH 01/17] bench: guest cycle harness + native single-constant check zisk/scripts/bench-cycles.sh runs the standard dumped-input suite (~/benchdata/zisk-inputs) through ziskemu, records steps, and verifies the committed `failures` publics word is zero. check_one mirrors the Zisk guest's one-work-item path natively so IX_* instrumentation can target a single expensive constant. --- crates/kernel/Cargo.toml | 7 +++ crates/kernel/examples/check_one.rs | 68 +++++++++++++++++++++++++++++ zisk/scripts/bench-cycles.sh | 48 ++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 crates/kernel/examples/check_one.rs create mode 100755 zisk/scripts/bench-cycles.sh diff --git a/crates/kernel/Cargo.toml b/crates/kernel/Cargo.toml index 996eab3e..ebb91120 100644 --- a/crates/kernel/Cargo.toml +++ b/crates/kernel/Cargo.toml @@ -36,5 +36,12 @@ quickcheck_macros = { workspace = true } name = "perf_check" path = "examples/perf_check.rs" +# Native single-constant check (one work item via the lazy-anon path the +# Zisk guest uses), so the `IX_*` instrumentation can target one expensive +# constant without re-checking its whole env. +[[example]] +name = "check_one" +path = "examples/check_one.rs" + [lints] workspace = true diff --git a/crates/kernel/examples/check_one.rs b/crates/kernel/examples/check_one.rs new file mode 100644 index 00000000..3d8fdf80 --- /dev/null +++ b/crates/kernel/examples/check_one.rs @@ -0,0 +1,68 @@ +//! Native single-constant check, mirroring the Zisk guest's reuse-mode path +//! (`zisk/guest/src/main.rs`): resolve a Lean NAME through the env's `named` +//! metadata to its ingress block, then `check_const` exactly that work item +//! with the lazy-anon TypeChecker. Exists so the kernel's `IX_*` +//! instrumentation (inert inside zkVM guests — see `src/lib.rs::env_var_os`) +//! can be pointed at one expensive constant without re-checking a whole env. +//! +//! IX_PERF_COUNTERS=1 cargo run --release --example check_one -- \ +//! ~/ix/init.ixe '_private.Init.Data.Range.Polymorphic.SInt.0.Int16.instRxcHasSize_eq' + +use std::env; +use std::fs; +use std::time::Instant; + +use ix_kernel::anon_work::build_anon_work; +use ix_kernel::env::KEnv; +use ix_kernel::id::KId; +use ix_kernel::mode::Anon; +use ix_kernel::tc::TypeChecker; +use ixon::constant::ConstantInfo as CI; +use ixon::env::Env as IxonEnv; + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .format_timestamp(None) + .init(); + let path = env::args().nth(1).expect("usage: check_one "); + let name = env::args().nth(2).expect("usage: check_one "); + let bytes = fs::read(&path).expect("read ixe"); + + let t_parse = Instant::now(); + let env = IxonEnv::get(&mut &bytes[..]).expect("decode env"); + eprintln!("[check_one] parse: {:>8.2?}", t_parse.elapsed()); + + // Name → constant address → ingress block (mirrors zisk-host + // `block_of_addr`): a projection's `block`, else the address itself. + let addr = env + .named + .iter() + .find(|e| e.key().pretty() == name || e.key().to_string() == name) + .map(|e| e.value().addr.clone()) + .unwrap_or_else(|| panic!("no constant named {name:?} in {path}")); + let block = match env.get_const(&addr).map(|c| c.info.clone()) { + Some(CI::IPrj(p)) => p.block, + Some(CI::CPrj(p)) => p.block, + Some(CI::RPrj(p)) => p.block, + Some(CI::DPrj(p)) => p.block, + _ => addr.clone(), + }; + + let work = build_anon_work(&env).expect("build_anon_work"); + let item = work + .iter() + .find(|it| *it.primary() == block) + .expect("work item for block"); + + let mut kenv = KEnv::::new(); + let mut tc = TypeChecker::::new_with_lazy_anon(&mut kenv, &env); + let kid = KId::::new(item.primary().clone(), ()); + let t_check = Instant::now(); + let result = tc.check_const(&kid); + eprintln!("[check_one] check: {:>8.2?} result: {:?}", t_check.elapsed(), result.is_ok()); + if let Err(e) = result { + eprintln!("[check_one] error: {e:?}"); + std::process::exit(1); + } +} diff --git a/zisk/scripts/bench-cycles.sh b/zisk/scripts/bench-cycles.sh new file mode 100755 index 00000000..f074b481 --- /dev/null +++ b/zisk/scripts/bench-cycles.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Cycle benchmark for the Zisk leaf guest across the standard input suite. +# +# Runs each dumped guest stdin in ~/benchdata/zisk-inputs through ziskemu, +# records steps (-m) and checks the committed `failures` publics word (-c, +# u32 word index 10) is zero — a non-zero value means the kernel REJECTED a +# constant and the run is invalid for benchmarking. +# +# Usage: +# bench-cycles.sh