You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
stabilize native object-cache keys for logical type fingerprints by avoiding nondeterministic Debug serialization
add a native executable link-cache manifest under the compile cache root to skip relinking when linker inputs, object fingerprints, output identity/content, toolchain inputs, and Perry binary identity match
expose additive JSON link_cache stats and cover the warm native skip path with unit and integration tests
Verification
cargo check -p perry
cargo test -p perry link_cache_
cargo test -p perry --test native_link_cache native_compile_skips_link_on_identical_second_build -- --nocapture
Earlier kept run with the same fix shape sampled Perry noop at 1.93s, small_change at 2.75s, and medium_change at 8.10s, so the benchmark remains noisy. A direct immediate repeat compile on the generated project deterministically reports "link_cache":{"linked":false,"skipped":true} in JSON and ran in 2.39s, which shows the remaining warm no-op cost is pre-link graph/codegen/object orchestration rather than the linker itself.
Remaining gap
This PR implements safe relink avoidance, not a full pre-graph build fingerprint. The next performance step is a build-level no-op manifest that can prove source graph/options/runtime/output currency before parsing/lowering/object orchestration.
P1 - Link cache can reuse stale executables when -L/-l or frameworks change.
The fingerprint only hashes explicit file args it recognizes, but Perry supports native-library inputs resolved indirectly through -L... + -l..., /LIBPATH: + foo.lib, -F + -framework, and pkg-config flags. Those real archives/frameworks are not content-hashed, so changing vendor/lib/libfoo.a or a vendored static framework can leave the command string unchanged and make the warm build skip relinking against an old executable.
Relevant spots:
crates/perry/src/commands/compile/link/link_cache.rs: file_inputs_from_arg only recognizes a small set of explicit file-shaped args.
crates/perry/src/commands/compile/link/mod.rs: native library metadata adds -F/-framework, -L/-l, /LIBPATH:, and pkg-config flags that can resolve link inputs without a stable file arg in the command.
DeepWiki's main-branch reference also calls out these native libs/frameworks as link-affecting inputs, so the manifest needs to resolve and hash them or decline to cache this shape.
P2 - Toolchain and inherited linker environment are not actually fingerprinted for common paths.
compute_link_cache_state hashes only Command's explicit env overrides and only hashes the linker executable if cmd.get_program() itself is an existing path. On Linux native builds Perry uses Command::new("cc"), so the cache records the literal string cc but not the resolved executable from PATH; on Windows, an existing LIB env is inherited rather than added to cmd.get_envs(). A compiler, SDK, LIB, LIBRARY_PATH, or PATH change can therefore produce a different link if run, while this cache skips and preserves the old binary.
Suggested fix direction: make the link cache either conservative by disabling itself for unresolved/linker-search inputs, or expand the fingerprint to include resolved library/framework files, resolved linker executable, and relevant inherited linker environment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
link_cachestats and cover the warm native skip path with unit and integration testsVerification
cargo check -p perrycargo test -p perry link_cache_cargo test -p perry --test native_link_cache native_compile_skips_link_on_identical_second_build -- --nocapturecargo build -p perry --releasepython3 scripts/run_arch_experiment.py --perry-bin /Users/andrew/.codex/worktrees/perry-native-warm-noop/target/release/perry --repeats 1 --tiers dep-wide-100k --modes native --keep-generatedFocused dep-wide-100k native sample
Baseline from post-rootcause report:
This branch, latest kept run:
Earlier kept run with the same fix shape sampled Perry noop at 1.93s, small_change at 2.75s, and medium_change at 8.10s, so the benchmark remains noisy. A direct immediate repeat compile on the generated project deterministically reports
"link_cache":{"linked":false,"skipped":true}in JSON and ran in 2.39s, which shows the remaining warm no-op cost is pre-link graph/codegen/object orchestration rather than the linker itself.Remaining gap
This PR implements safe relink avoidance, not a full pre-graph build fingerprint. The next performance step is a build-level no-op manifest that can prove source graph/options/runtime/output currency before parsing/lowering/object orchestration.