From be7930b39d1383f754ca94124ddf0ce722673d00 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Sun, 23 Aug 2026 15:25:37 -0400 Subject: [PATCH] conformance: wizer-pre-initialize the composed leg's suite (#372) --- Cargo.lock | 72 +++++++++++++++++++++++++++++++ conformance/driver-ct/Cargo.toml | 2 +- conformance/driver-ct/justfile | 20 ++++++++- conformance/driver-ct/src/main.rs | 66 +++++++++++++++++++--------- 4 files changed, 137 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86eb438d..9c8b90ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,6 +157,12 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + [[package]] name = "bitflags" version = "2.13.1" @@ -382,6 +388,7 @@ dependencies = [ "tokio", "wasmtime", "wasmtime-wasi", + "wasmtime-wizer", ] [[package]] @@ -1577,6 +1584,39 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "logos" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "syn 2.0.119", +] + +[[package]] +name = "logos-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" +dependencies = [ + "logos-codegen", +] + [[package]] name = "mach2" version = "0.6.0" @@ -2104,6 +2144,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "rend" version = "0.5.4" @@ -2884,6 +2930,18 @@ dependencies = [ "wasmparser 0.254.0", ] +[[package]] +name = "wasm-wave" +version = "0.252.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054d19e2b53e3bf158deac6e8cc003d9eaf3ec7ecaef579988ef7b5c666f9546" +dependencies = [ + "anyhow", + "logos", + "thiserror 2.0.19", + "wit-parser 0.252.0", +] + [[package]] name = "wasmparser" version = "0.243.0" @@ -2994,6 +3052,7 @@ dependencies = [ "tempfile", "wasm-compose", "wasm-encoder 0.252.0", + "wasm-wave", "wasmparser 0.252.0", "wasmtime-environ", "wasmtime-internal-cache", @@ -3247,6 +3306,19 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "wasmtime-wizer" +version = "47.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31523af61f453d106d220a8579cb983a335e3c4cdd6b55bf07f330c990bb9b7" +dependencies = [ + "log", + "rayon", + "wasm-encoder 0.252.0", + "wasmparser 0.252.0", + "wasmtime", +] + [[package]] name = "wast" version = "35.0.2" diff --git a/conformance/driver-ct/Cargo.toml b/conformance/driver-ct/Cargo.toml index 620d9800..c3ea2c04 100644 --- a/conformance/driver-ct/Cargo.toml +++ b/conformance/driver-ct/Cargo.toml @@ -14,7 +14,7 @@ name = "compat" path = "src/bin/compat.rs" [dependencies] -component-test-runner = { workspace = true } +component-test-runner = { workspace = true, features = ["wizer"] } polymorph-webcrypto-wasmtime = { path = "../../rust/wasmtime" } wasmtime = { version = "47", features = ["component-model", "component-model-async", "async", "runtime"] } wasmtime-wasi = "47" diff --git a/conformance/driver-ct/justfile b/conformance/driver-ct/justfile index 25f939bb..e6bdf6cd 100644 --- a/conformance/driver-ct/justfile +++ b/conformance/driver-ct/justfile @@ -11,6 +11,7 @@ ct-tools := root + "/target/ct-tools" ct := ct-tools + "/bin/component-test" ct-runner := ct-tools + "/bin/ct-runner" guest := root + "/target/wasm32-wasip2/release/conformance_guest_ct.wasm" +guest-wizened := root + "/target/conformance-guest-ct-wizened.wasm" signing := root + "/target/wasm32-wasip2/release/conformance_signing_guest_ct.wasm" provider := root + "/target/wasm32-wasip2/release/polymorph_webcrypto_guest_provider.wasm" composed := root + "/target/conformance-composed-ct.wasm" @@ -363,9 +364,26 @@ build-provider: # aggregate's cross-check against targets.toml. The signing suite never # runs composed: its world imports ecdsa-sign, so it cannot even link # against the provider (the class-d recipe asserts exactly that). +# +# The suite is wizer-pre-initialized BEFORE composition: ct-runner's +# default fresh-instance-per-case containment pays the suite's registry +# construction per case, which dominated this leg's wall time; the +# wizened suite is born with the registry built, keeping per-case +# isolation at a fraction of the cost (the residual per-case tax is the +# census handle lift — measured ~2.6x less total CPU on this corpus). +# The order is forced from both sides: wasmtime-wizer cannot process +# the composed bundle (nested components with modules), and the bare +# suite's `polymorph:webcrypto/*` imports keep the shipped plain-suite +# `component-test wizen` out — so the driver's own `--wizen` mode +# (`wizen_with` over the same full-support linker the wasmtime leg +# runs) wizens the bare suite, and `wac plug` composes the result. +# --suite-artifact keeps the envelope identity and tags on the +# canonical bare artifact; the wizened enumeration is census-identical +# (the aggregate's lock binding gates that on every run). run-composed: build build-provider _ct-tools mkdir -p results - wac plug {{guest}} --plug {{provider}} -o {{composed}} + {{root}}/target/release/ct-driver {{guest}} --wizen {{guest-wizened}} + wac plug {{guest-wizened}} --plug {{provider}} -o {{composed}} {{ct-runner}} {{composed}} --jobs 8 --jsonl \ --suite-artifact {{guest}} \ --missing ecdsa-sign --target composed > results/composed.jsonl diff --git a/conformance/driver-ct/src/main.rs b/conformance/driver-ct/src/main.rs index fc80ebf4..cf95a9d7 100644 --- a/conformance/driver-ct/src/main.rs +++ b/conformance/driver-ct/src/main.rs @@ -3,7 +3,7 @@ //! //! Usage: ct-driver [--jsonl] [--missing f1,f2,...] //! [--jobs N] [--cases-per-instance N] [--target key] [--only substring] -//! [--enumerate] +//! [--enumerate] [--wizen ] use std::path::PathBuf; use std::process::ExitCode; @@ -48,6 +48,25 @@ impl RunnerView for Data { } } +fn make_data() -> Data { + Data { + wasi: WasiCtxBuilder::new().inherit_stderr().build(), + table: ResourceTable::new(), + ct: CtCtx::default(), + webcrypto: WasiWebcryptoCtx::default(), + } +} + +/// The full-support target: every gated interface enabled. +fn configure_linker(linker: &mut wasmtime::component::Linker) -> wasmtime::Result<()> { + let mut options = LinkOptions::default(); + options + .sha1_checked(true) + .rsa_sign(true) + .rsa_oaep_decrypt(true); + add_to_linker_with_options(linker, &options) +} + fn main() -> ExitCode { match run() { Ok(code) => code, @@ -67,6 +86,7 @@ fn run() -> Result { let mut target: String = "wasmtime-rustcrypto".into(); let mut only: Option = None; let mut enumerate = false; + let mut wizen_out: Option = None; let mut args = std::env::args().skip(1); while let Some(arg) = args.next() { match arg.as_str() { @@ -101,6 +121,12 @@ fn run() -> Result { } "--jsonl" => mode = OutputMode::Jsonl, "--enumerate" => enumerate = true, + "--wizen" => { + wizen_out = + Some(PathBuf::from(args.next().ok_or_else(|| { + anyhow::anyhow!("--wizen needs an output path") + })?)); + } _ if suite.is_none() => suite = Some(PathBuf::from(arg)), other => bail!("unexpected argument `{other}`"), } @@ -109,7 +135,7 @@ fn run() -> Result { anyhow::anyhow!( "usage: ct-driver [--jsonl] [--missing f1,f2,...] \ [--jobs N] [--cases-per-instance N] [--target key] [--only substring] \ - [--enumerate]" + [--enumerate] [--wizen ]" ) })?; let suite_name = suite @@ -118,25 +144,23 @@ fn run() -> Result { .unwrap_or("suite") .to_string(); - let runner = Runner::with_data( - &suite, - || Data { - wasi: WasiCtxBuilder::new().inherit_stderr().build(), - table: ResourceTable::new(), - ct: CtCtx::default(), - webcrypto: WasiWebcryptoCtx::default(), - }, - |linker| { - // The full-support target: every gated interface enabled. - let mut options = LinkOptions::default(); - options - .sha1_checked(true) - .rsa_sign(true) - .rsa_oaep_decrypt(true); - add_to_linker_with_options(linker, &options) - }, - ) - .map_err(|e| anyhow::anyhow!("{e:#}"))?; + // Wizen mode: pre-initialize the suite — its own `all()` runs here, + // once, and the built registry is snapshotted into the emitted + // artifact, so every future instance skips registry construction. + // The suites import `polymorph:webcrypto/*`, which only this driver's + // linker can satisfy (`component-test wizen` serves plain suites + // only), hence `wizen_with` with the same store data and linker + // setup the run path uses. + if let Some(out) = wizen_out { + let bytes = std::fs::read(&suite)?; + let wizened = component_test_runner::wizen::wizen_with(&bytes, make_data, configure_linker) + .map_err(|e| anyhow::anyhow!("{e:#}"))?; + std::fs::write(&out, wizened)?; + return Ok(ExitCode::SUCCESS); + } + + let runner = Runner::with_data(&suite, make_data, configure_linker) + .map_err(|e| anyhow::anyhow!("{e:#}"))?; // The suite's full case enumeration (one name per line): the // `lock --leaves` input that pins the generated rows' leaves.