Skip to content

perf: cache resolved zig command in wrapper scripts to skip per-invocation probes - #469

Merged
messense merged 1 commit into
mainfrom
perf-cache-zig-command
Aug 26, 2026
Merged

perf: cache resolved zig command in wrapper scripts to skip per-invocation probes#469
messense merged 1 commit into
mainfrom
perf-cache-zig-command

Conversation

@messense

@messense messense commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

Addresses the per-invocation overhead measured in #244.

find_zig() runs on every cargo-zigbuild zig cc invocation and always spawned two processes before doing any work:

  1. python -m ziglang version — paying full Python interpreter startup (~15ms) just to fail on systems without the pip package,
  2. zig version — ~31ms of zig startup for validation, even though CARGO_ZIGBUILD_ZIG_VERSION already carries the version.

The toolchain was already resolved and validated when the wrapper script was generated, so re-probing per compile is pure waste — for C-heavy builds it's paid hundreds of times.

This exports the resolved command as CARGO_ZIGBUILD_ZIG_COMMAND (+ CARGO_ZIGBUILD_ZIG_COMMAND_ARGS for the python -m ziglang mode) in the generated sh and bat wrappers, and has find_zig() trust it when the path still exists — falling back to the normal probe order if it doesn't (e.g. zig was moved between builds; the next wrapper regeneration re-resolves).

Numbers (macOS, zig 0.16.0, hyperfine, real-build env)

before after
wrapper -### call 87 ms 44 ms
raw zig cc -### 33 ms 33 ms
overhead ~52 ms ~11 ms

The remaining ~11ms is sh + cargo-zigbuild binary startup and arg filtering.

Verified: cargo test --lib passes; real builds for aarch64-apple-darwin and x86_64-unknown-linux-gnu.2.17 regenerate wrappers with the new exports and build cleanly. Clippy warnings are pre-existing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W1Kk6AucizDRZdBDVGipXF

…ation probes

find_zig() ran on every compiler invocation and always spawned
`python -m ziglang version` (paying Python interpreter startup just to
fail on systems without the pip package) and then `zig version` for
validation — ~40ms per zig cc call even though the toolchain was already
resolved and validated when the wrapper was generated.

Export the resolved command as CARGO_ZIGBUILD_ZIG_COMMAND(_ARGS) in the
generated wrapper scripts and trust it in find_zig() when the path still
exists, falling back to probing otherwise.

Measured on macOS (zig 0.16.0): wrapper overhead vs raw zig cc drops from
~52ms to ~11ms per invocation (85ms -> 44ms total for a -### call).

Fixes #244

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1Kk6AucizDRZdBDVGipXF
@messense
messense enabled auto-merge (squash) August 26, 2026 13:45
@messense
messense merged commit 100fcb7 into main Aug 26, 2026
49 checks passed
@messense
messense deleted the perf-cache-zig-command branch August 26, 2026 14:47
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.

1 participant