Repository navigation
Parse bun.lock once per scan (#1606) - #1700
Merged
Mikola Lysenko (mikolalysenko) merged 4 commits intoOct 23, 2026
Merged
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A Bun scan read the same bun.lock three times (the lock inventory, VEX discovery and the hosted redirect), and on a 3000-package lock each parse cost more than the .bun store walk #599 added. Those readers now share one parse of an unchanged text, so Bun rescans and hosted scans spend less CPU. A changed lock is always parsed again. Refs #1606 Assisted-by: Claude Code:claude-opus-5-5
The shared bun.lock parse kept a copy of the whole text to recognize it, which added to a scan's peak memory. It now checks a text against the lines it already holds, and does not keep a refused lock. Refs #1606 Assisted-by: Claude Code:claude-opus-5-5
Address review: the readers now get the shared parse itself instead of a wrapper, the hosted redirect copies the lock's lines only when it splices one, and the vendored preflight, which read bun.lock once per patched package, uses the shared parse too. Refs #1606 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 23, 2026 21:53
Collaborator
Author
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit cdbe831. Configure here.
Tanmay Singla (Tanmay182003)
approved these changes
Oct 23, 2026
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-bun-store-liveness-walk-cost
branch
October 23, 2026 22:55
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1606
Summary
A Bun scan parsed the same
bun.lockthree times: once in the lock inventory, once in VEX discovery and once in the hosted redirect. The vendored preflight also parsed it once per patched package. On the bench's 3000-package lock, each parse costs about 29M instructions, more than half of what the.bunstore walk (#599) added. The readers now share one parse of an unchanged lock text.bun-isolated/rescanis 8–14% faster thanmainand back to the issue's basecc938aa6.Root cause
Callgrind of
bun-isolated/rescanon the bench fixture:cc938aa6(issue base)main3114a28The +46M from
cc938aa6tomainis the.bunstore liveness walk (#599,live_bun_store_entries_sync/read_bun_store_node_modules_sync), as #1693 suspected. That walk is already lean: most of its cost is the per-entrynode_moduleslistings the orphan check needs, and cutting them would weaken #599. The largest avoidable cost, on both builds, is older:BunTextLock::parserunning 3× per scan, about 16% of all instructions. It also explains the non-isolatedbun/hostedregression in the issue.Fix
formats::bun::BunTextLock::parse_sharedkeeps the last lock it parsed (Arc<BunTextLock>). A text whosesplit('\n')lines equal that lock'slinesgets the same parse back. Any other text is parsed again, so a changed lock never reads stale. A refused lock isn't kept. No copy of the text is kept either; the match is checked against the lines the parse already holds.lock_inventory::bun::bun_text_entries(inventory and VEX discovery),parse_bun_hosted_lock(hosted redirect and hosted restore), and the vendored preflight invendor/bun_lock.rs.Cowof the lines, which copies them only on the first edit. The hosted restore always edits, so it copies up front.Benchmarks
socket-patch-bench compare, 20 interleaved pairs on this sandbox (4 vCPU). Base ismain3114a28:bun/hostedbun/rescanbun-isolated/hostedbun-isolated/rescannpm/rescan,pnpm/rescan,bundler/*(controls)Against the issue's base
cc938aa6,bun-isolated/rescanwent from +21.3% to +5.3% [+0.6, +9.0] in the paired compare (bench runmedians: 116.3 ms base, 117.0 ms this PR).bun/hostedandbun/rescanare at -0.1% and -0.4%.Peak RSS, from
socket-patch-bench runmedians of 15 runs: this PR adds about 0.7 MiB overmainon the Bun rescans (+2%) and nothing on npm, because the last lock's parse stays alive. The compare table's RSS column moved ±7–10% even onnpm/pnpm, which never readbun.lock, so this run's RSS deltas are noise.mainis already about 3.3 MiB abovecc938aa6onnpm/rescanas well as on Bun, so that growth isn't Bun-specific (see #1607's RSS slice).Tests
formats::bun::tests::same_text_is_parsed_oncechanged_text_is_parsed_againa_prefix_or_extension_is_another_textrefusals_are_not_keptshared_parse_reads_like_the_parsesocket-patch-benchtables abovecc938aa6Scan output is unchanged: the JSON of
bun-isolated/rescanis byte-identical betweenmainand this PR, and every bench scenario passes the harness's validation.Local runs:
cargo fmt --all -- --checkandcargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-core --all-features: 6705 lib tests pass, plus every integration test binary. Four lib tests fail the same way onmainin this sandbox: they are permission-denied tests, and the sandbox runs as root so chmod can't make writes fail (copy_tree,vlt_heal,pypi_poetry,pypi_requirements).cargo test -p socket-patch-cli --all-features --lib: 933 pass.-- --include-ignoredone2e_redirect_bun_build,e2e_vendor_bun_build,mode_migration_bun,in_process_vendor_bun_takeover,vendor_eject_bun_lockb,e2e_vex_redirectande2e_vex_vendor, with real Bun 1.4.4: all pass.e2e_bun_lockb: 22 pass, 2 fail identically onmainhere.binary_shared_bundled_record_hosted_pin_is_managedneedspatches-api.socket.dev.workspace_text_migration_heals_on_rerunasserts Bun's ownbun.lockb → bun.lockmigration output, which local Bun 1.4.4 writes differently from CI's pinned 1.4.2.CI on
cdbe831: every check passed or was skipped by the PR tier, includingci-ok,coverage,clippyand the Bun 1.4.2 e2e leg. Cursor Bugbot found no issues.Review notes (
/code-review high)Fixed in
cdbe831: the vendored preflight parsing once per package, the redirect always cloning the lines, and the extraBunEntrieswrapper.Not fixed:
DiskSnapshotwould free it at the end of a scan, but the redirect and the vendored preflight don't receive the snapshot, so that means threading it through those call paths.bun.lockfiles parses each one, as before. The added line comparison stops at the first differing line, and member locks differ in theworkspacesblock near the top.The npm, PyPI and gem wrappers only dispatch the binary, so they need no change.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YB4wa2mtpEejKGP7bZ3NZF