Skip to content

Complete wasm-embedded-inference spike with wazero integration - #164

Merged
jeduden merged 2 commits into
mainfrom
claude/plan-65-wasm-inference-spike
Apr 22, 2026
Merged

Complete wasm-embedded-inference spike with wazero integration#164
jeduden merged 2 commits into
mainfrom
claude/plan-65-wasm-inference-spike

Conversation

@jeduden

@jeduden jeduden commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

This PR completes the WASM-embedded-inference spike (plan 65), implementing a proof-of-concept that embeds a WebAssembly classifier artifact using go:embed and hosts it with the wazero runtime. The spike evaluates whether WASM can provide a viable inference path for mdsmith with no runtime dynamic library dependencies.

Key Changes

  • WASM guest implementation (wasm/main.go): A minimal WASI reactor module that reuses the plan-64 linear classifier package verbatim, exposing three wasmexport functions (alloc, free, classify) for host-guest communication via linear memory.

  • Host harness (main.go): A comprehensive benchmark and determinism-verification tool that:

    • Loads the embedded wasm artifact via go:embed
    • Instantiates it with wazero (v1.11.0, using the default wazevo optimizing compiler)
    • Measures cold-start compile time, per-call latency (avg/p50/p95/max), memory overhead, and determinism across process restarts
    • Compares against the MDS029 heuristic, pure-Go classifier (plan 64), and yzma embedded baselines
  • Build infrastructure (run.sh): Automated script that:

    • Compiles the wasm guest with GOOS=wasip1 GOARCH=wasm -buildmode=c-shared
    • Builds the host harness and runs determinism checks across five process restarts
    • Measures binary-size delta by building mdsmith with and without the spike_wasm_classifier tag
    • Captures all metrics to bench.txt and size.txt
  • Size-measurement hooks (internal/rules/concisenessscoring/wasmclassifier/embed.go, cmd/mdsmith/spike_wasm_classifier.go): Build-tag-gated stubs that force-link the embedded wasm artifact and wazero runtime so binary-size impact can be measured in isolation.

  • Comprehensive documentation (updated README.md): Detailed findings including:

    • Determinism confirmation (5 in-process + 5 cross-process runs, all identical digest)
    • Latency metrics: ~2,022 us avg, 2,464 us p95 (vs. 3.38 us for pure-Go)
    • Memory: 109 MB RSS after bench (vs. 7.8 MB for pure-Go)
    • Binary cost: 4.17 MB delta (3.99 MB wasm artifact + 181 KB wazero/WASI)
    • Recommendation: reject this path — the pure-Go classifier already delivers deterministic output with 480 B binary cost and 3 us latency; wasm adds no capability while incurring 600x latency penalty and 14x memory overhead
  • Plan status update (plan/65_spike-wasm-embedded-inference.md): Marked complete with all acceptance criteria met.

Notable Implementation Details

  • Module loading strategy: One module instance is reused for all calls; re-instantiating per call would incur the ~1.7 s wazero compile cost repeatedly. The host calls _initialize explicitly after instantiation (reactor-module semantics).

  • Memory safety: Host-guest communication uses linear memory with explicit alloc/free calls. The guest returns a packed int64 (outPtr<<32)|outLen pointing to a static 4 KB output buffer containing JSON results.

  • Determinism: Outputs are byte-for-byte identical across in-process repeats and process restarts, with SHA256 digest pinning recommended for integrity checks.

  • Fallback boundaries: Documented recommended guards (compile-time build tag, runtime instantiation with fallback to heuristic on error, per-call timeout wrapper, verbose diagnostics).

  • Artifact update workflow: Safe path defined with SHA256 pinning, version tracking, and determinism validation before shipping.

Rationale for Rejection

The spike conclusively demonstrates that while wasm provides deterministic, sandboxed execution with no external dynamic

https://claude.ai/code/session_014iGcShL7oVcZVoYk4JSPpq

Compile the plan-64 pure-Go classifier to a wasip1 reactor module
(-buildmode=c-shared) and host it via wazero v1.11.0. Guest exports
alloc/free/classify; host initializes, writes input into guest linear
memory, reads a JSON result back. Measured against the plan-64 and
plan-63 (yzma) spikes on the same six-sample corpus.

Captured on Linux amd64, Go 1.25.8, ROUNDS=4000:

- determinism: 1 unique hash across 5 in-process + 5 cross-process
  runs (digest 7a1dc22...)
- avg latency 2,022 us (p50 1,952 us, p95 2,464 us); ~600x go-native,
  ~25x faster than yzma
- RSS post-bench 109 MB; guest cold-compile 1,699 ms
- binary-size delta +4,174,718 B (wasm 3,993,759 B + wazero 181 KB)

Recommendation: reject for the current classifier size. The pure-Go
classifier (plan 64) already ships the same deterministic output in
480 B, 3 us avg latency, and 7.8 MB RSS; wasm adds no capability the
Go path lacks. Reopen this path only if a future classifier is not
practically authorable in pure Go or requires the wazero sandbox.

Mark plan 65 complete.

https://claude.ai/code/session_01FJ96zwAGrCK76WKt1szp1F
Copilot AI review requested due to automatic review settings April 22, 2026 18:54
@codecov

codecov Bot commented Apr 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.03%. Comparing base (143275b) to head (96af29e).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #164   +/-   ##
=======================================
  Coverage   88.03%   88.03%           
=======================================
  Files         110      110           
  Lines       14106    14106           
=======================================
  Hits        12418    12418           
  Misses       1228     1228           
  Partials      460      460           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes plan 65’s WASM-embedded inference spike by adding a WASI/wasip1 guest module, a wazero-based host benchmark harness, build automation, and documentation of performance/determinism/size findings (with a recommendation to reject WASM for this use case).

Changes:

  • Added a WASM guest (wasip1) exposing alloc, free, and classify, plus a host harness that embeds and executes the artifact via wazero for determinism/latency/memory measurement.
  • Added a build+benchmark script and build-tag-gated linker hooks to measure mdsmith binary-size deltas when force-linking wazero + the embedded wasm artifact.
  • Updated spike documentation and plan status to record results and mark the plan complete.

Reviewed changes

Copilot reviewed 9 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plan/65_spike-wasm-embedded-inference.md Marks tasks/acceptance criteria complete and links to spike findings.
internal/rules/concisenessscoring/wasmclassifier/embed.go Build-tag-gated embed + force-link package for artifact + wazero/WASI size measurement.
cmd/mdsmith/spike_wasm_classifier.go Build-tag-gated init hook to keep embedded wasm reachable for binary-size delta measurement.
docs/research/conciseness/spikes/wasm-embedded-inference/wasm/main.go WASM guest implementation exporting alloc/free/classify over linear memory.
docs/research/conciseness/spikes/wasm-embedded-inference/main.go Host harness that embeds the wasm artifact, instantiates via wazero, and benchmarks/digests outputs.
docs/research/conciseness/spikes/wasm-embedded-inference/run.sh Automation to build the guest, run determinism/bench, and measure mdsmith size delta.
docs/research/conciseness/spikes/wasm-embedded-inference/README.md Documents methodology, metrics, and recommendation to reject WASM path.
go.mod / go.sum Adds wazero dependency for the spike artifacts/size measurement path.
PLAN.md Updates plan table to show plan 65 complete.
.gitignore Ignores generated wasm artifact copies and the .tmp/ output directory used by the spike.

Comment thread docs/research/conciseness/spikes/wasm-embedded-inference/wasm/main.go Outdated
Comment thread docs/research/conciseness/spikes/wasm-embedded-inference/main.go Outdated
Address Copilot review comments on PR #164:

- Guest classify(): return 0 when length>0 but ptr==0 so a bad host
  call cannot hit unsafe.Slice on a null pointer in wasm linear
  memory.
- Guest classify(): check encoded JSON length before copying into
  the static 4 KB outputBuf. On overflow, return -1 so the host can
  raise rather than silently decoding a truncated buffer.
- Host Classify(): skip alloc/free and memory.Write when the input
  is empty; call classify(0, 0) directly. Matches the guest's
  length==0 fast path.
- Host Classify(): detect the guest's new negative sentinel and
  return a "guest signaled output truncation" error.

Rebench confirms determinism digest is unchanged
(7a1dc22...) and all per-sample risk scores are identical. Binary
delta shifts by 24 bytes (new guard code). No change to the spike's
conclusions.

https://claude.ai/code/session_014iGcShL7oVcZVoYk4JSPpq
@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Apr 22, 2026
@jeduden

jeduden commented Apr 22, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden

jeduden commented Apr 22, 2026

Copy link
Copy Markdown
Owner Author

🔵 Merge Queue — CI running

Merged into batch branch merge-queue/batch-164-1776885084. View CI run.

Next: No action needed — you'll be notified when CI completes.

@jeduden jeduden removed the queue:active Applied automatically when a PR is in an active batch label Apr 22, 2026
@jeduden

jeduden commented Apr 22, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — merged

This PR landed on main via commit d983848. CI run that validated the merge.

Next: Done — nothing more to do here.

@jeduden
jeduden merged commit d983848 into main Apr 22, 2026
12 checks passed
Sign up for free to 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