Skip to content

Perf regression: yarn-classic/hosted wall +165% (5096c41a, #1328) #1423

Closed

Description

[agent] Bench: yarn-classic/hosted wall time is +165% and yarn-classic/rescan +153% on today's main (17793173), compared with f3c6313a (the previous bench run, 2026-10-09). The hosted scan also makes 60 more requests (127 → 187), one GET per patched package's served tarball.

Culprit: 5096c41a, #1328 ("Fix fragmentless yarn classic hosted pins (#558)"). This was found by profiling, not by bisect builds, and git log -L puts the hot function's only change in that range in that commit.

Same-machine interleaved compare

Base f3c6313a → head 17793173, on a 4 vCPU Intel Xeon @ 2.10GHz cloud sandbox. An A/A run on the same machine was clean.

scenario round base wall head wall Δ wall [95% CI] Δ CPU Δ RSS requests
yarn-classic/hosted 1 (15 pairs) 176.7 ms 444.5 ms +159.2% [+128.4, +167.9] +137.6% +4.7% 127 → 187 (+60)
yarn-classic/hosted 2 (20+10 pairs) 171.8 ms 462.0 ms +164.8% [+149.2, +178.2] +144.6% +4.2% 127 → 187 (+60)
yarn-classic/rescan 1 132.6 ms 342.9 ms +153.7% [+142.0, +170.3] +123.5% +5.7% 127
yarn-classic/rescan 2 123.4 ms 314.3 ms +152.7% [+140.7, +168.2] +123.8% +4.8% 127

The rescan makes no extra requests, so most of the cost is local CPU work rather than the tarball downloads.

Hot spot

Callgrind on the head binary, yarn-classic/rescan (3000 packages, 60 patched), inclusive instructions:

93.8%  scan::run_scan
72.3%    scan::hosted::run_redirect_selected_untracked
67.8%      hosted::engine::yarn_classic_artifact_targets
60.8%        hosted::engine::classic_locks_registry_copy
43.4%          formats::yarn::blocks::scan_blocks
10.5%          drop_in_place<Vec<LockBlock>>
 8.0%          formats::yarn::patterns::split_key_patterns

yarn_classic_artifact_targets runs classic_locks_registry_copy(lock, name, version) once per candidate dep. Each call re-runs scan_blocks over the whole yarn.lock and splits every block's key patterns, so the cost is O(patched deps × lock size). The registry-copy filter also runs before the cheap lock.contains("\"<url>#") test, so a rescan pays it for every dep even though every dep is already pinned and nothing gets fetched.

Possible fixes:

Repro

export CARGO_PROFILE_PERF_INHERITS=release CARGO_PROFILE_PERF_LTO=thin CARGO_PROFILE_PERF_STRIP=none
git worktree add /tmp/base f3c6313a && (cd /tmp/base && CARGO_TARGET_DIR=/tmp/tb cargo build --locked --profile perf -p socket-patch-cli)
CARGO_TARGET_DIR=/tmp/th cargo build --locked --profile perf -p socket-patch-cli -p socket-patch-bench
/tmp/th/perf/socket-patch-bench compare --base /tmp/tb/perf/socket-patch --head /tmp/th/perf/socket-patch -f '^yarn-classic/' --runs 20

On main, the yarn-classic scenarios fail validation (60 unexpected tarball GETs) until the bench fixture update in #1422 lands. The PR serves real .tgz artifacts. Run the repro from that PR's branch.

Runner: nproc 4, Intel(R) Xeon(R) Processor @ 2.10GHz.


Generated by Claude Code

Activity

  1. mikolalysenko commented on Oct 12, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: yarn classic hosted artifact-target selection re-scans the whole yarn.lock once per patched dep). Branch: agent/fix-yarn-classic-registry-copy-rescan. Claim-ID: 2026-10-12T08:20:57Z-4fc440


    Generated by Claude Code

  2. mikolalysenko commented on Oct 12, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR: #1426


    Generated by Claude Code

  3. added 6 commits that reference this issue on Oct 12, 2026
    d9cdf55
    6bb96fd
    ee84a85
    286280b
    a60710e
    9d0c1bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions