Skip to content

perf(pm): prioritize demand install downloads#2997

Closed
elrrrrrrr wants to merge 1 commit into
exp/pm-install-clone-batch-completionsfrom
exp/pm-install-download-priority-v2
Closed

perf(pm): prioritize demand install downloads#2997
elrrrrrrr wants to merge 1 commit into
exp/pm-install-clone-batch-completionsfrom
exp/pm-install-download-priority-v2

Conversation

@elrrrrrrr
Copy link
Copy Markdown
Contributor

@elrrrrrrr elrrrrrrr commented May 19, 2026

Summary

Experiment for p3 cold install download priority.

  • keep full lockfile tarball prefetch enabled
  • when BFS ensure_clone needs a package that is still only pending from preload, move that download to the front of the pending queue
  • do not interrupt active downloads and do not reduce global download/extract/clone concurrency

Rationale

prefetch_lock_downloads can enqueue the whole lockfile before depth-by-depth install starts. A later BFS demand currently attaches a waiter but keeps the tarball at its original preload position. This experiment keeps preload throughput while letting the current BFS frontier unblock earlier.

Verification

  • cargo fmt
  • cargo test -p utoo-pm install_scheduler
  • cargo clippy -p utoo-pm --all-targets -- -D warnings --no-deps

GHA Benchmark

Conclusion: negative / not worth integrating. Two GHA runs did not improve p3; the rerun regressed p3 clearly.

Baseline is #2989 latest Linux/npmjs (26102983933).

phase #2989 utoo #2997 run 1 (26107409974) #2997 run 2 (26108512218) conclusion
p0 full cold 7.34s, 65.1K/45.7K ctx 7.46s, 71.9K/49.1K ctx 7.71s, 65.9K/46.9K ctx no win
p3 cold install 5.30s, 52.4K/33.8K ctx 5.43s, 57.3K/43.7K ctx 8.02s, 78.6K/46.1K ctx regression
p4 warm link 2.20s, 7.9K/4.6K ctx 2.06s, 7.6K/4.4K ctx 2.00s, 7.5K/4.4K ctx p4-only win, not enough

The hypothesis was plausible, but GHA data says pending download reprioritization adds instability without improving the p3 cold path.

@elrrrrrrr elrrrrrrr added A-Pkg Manager Area: Package Manager benchmark Run pm-bench on PR labels May 19, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a mechanism to prioritize pending downloads when a new waiter is added to an existing download key. This is achieved through a new prioritize_download method that moves the relevant package to the front of the download queue. A unit test was also added to verify this behavior. Feedback was provided regarding the performance of the prioritize_download function, specifically noting that calling package.key() inside a linear search results in unnecessary string allocations; a more efficient comparison method was suggested.

Comment on lines +424 to +437
fn prioritize_download(&mut self, key: &str) {
// A preloaded tarball may become the current BFS frontier's blocker
// later. Promote only pending work; active downloads keep running.
let Some(index) = self
.download_queue
.iter()
.position(|package| package.key() == key)
else {
return;
};
if let Some(package) = self.download_queue.remove(index) {
self.download_queue.push_front(package);
}
}
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.

medium

The prioritize_download function performs a linear search over the download_queue. In the current implementation, package.key() is called for every element in the queue until a match is found. Since key() allocates a new String via format!, this results in a large number of temporary allocations in the scheduler's hot loop, especially for large dependency trees where the queue might contain thousands of items. You can avoid these allocations by comparing the name and version fields directly against the provided key string.

    fn prioritize_download(&mut self, key: &str) {
        // A preloaded tarball may become the current BFS frontier's blocker
        // later. Promote only pending work; active downloads keep running.
        let Some(index) = self.download_queue.iter().position(|package| {
            package.name.len() + package.version.len() + 1 == key.len()
                && key.as_bytes().get(package.name.len()) == Some(&b'@')
                && key.starts_with(&package.name)
                && key.ends_with(&package.version)
        }) else {
            return;
        };
        if index > 0 {
            if let Some(package) = self.download_queue.remove(index) {
                self.download_queue.push_front(package);
            }
        }
    }

@elrrrrrrr elrrrrrrr added benchmark Run pm-bench on PR and removed benchmark Run pm-bench on PR labels May 19, 2026
@elrrrrrrr
Copy link
Copy Markdown
Contributor Author

Closing this draft as a negative experiment: two GHA runs did not improve p3, and the rerun regressed p3 clearly.

@elrrrrrrr elrrrrrrr closed this May 19, 2026
@github-actions
Copy link
Copy Markdown

📊 pm-bench-phases · faad196 · linux (ubuntu-latest)

Workflow run — ant-design

PMs: utoo (this branch) · utoo-npm (latest published) · bun (latest)

npmjs.org

p0_full_cold

PM wall ±σ user sys RSS pgMinor
bun 8.95s 0.06s 10.27s 10.41s 668M 308.7K
utoo-next 8.54s 0.16s 10.49s 12.85s 999M 126.7K
utoo-npm 9.66s 1.76s 10.81s 13.08s 1018M 130.5K
utoo 8.10s 0.34s 11.78s 11.45s 1017M 145.1K
PM vCtx iCtx netRX netTX cache node_mod lock
bun 16.6K 18.6K 1.19G 7M 1.86G 1.75G 1M
utoo-next 137.6K 108.5K 1.16G 5M 1.71G 1.70G 2M
utoo-npm 148.9K 113.9K 1.16G 6M 1.71G 1.70G 2M
utoo 73.5K 57.2K 1.16G 7M 1.71G 1.70G 2M

p1_resolve

PM wall ±σ user sys RSS pgMinor
bun 2.32s 0.05s 3.87s 1.12s 492M 183.9K
utoo-next 3.18s 0.07s 5.43s 2.15s 614M 80.4K
utoo-npm 3.24s 0.02s 5.50s 2.18s 611M 80.7K
utoo 2.50s 0.09s 5.99s 1.74s 642M 120.6K
PM vCtx iCtx netRX netTX cache node_mod lock
bun 11.7K 3.8K 203M 3M 108M - 1M
utoo-next 77.3K 94.8K 200M 3M 7M 3M 2M
utoo-npm 77.5K 97.8K 200M 3M 7M 3M 2M
utoo 16.4K 20.1K 202M 3M 7M 3M 2M

p3_cold_install

PM wall ±σ user sys RSS pgMinor
bun 6.80s 0.13s 6.27s 10.21s 618M 206.6K
utoo-next 8.38s 2.79s 5.01s 11.33s 527M 65.3K
utoo-npm 6.47s 0.48s 5.07s 11.06s 534M 63.3K
utoo 5.44s 0.22s 5.49s 9.63s 482M 56.2K
PM vCtx iCtx netRX netTX cache node_mod lock
bun 5.2K 7.9K 1019M 4M 1.76G 1.76G 1M
utoo-next 121.8K 53.0K 990M 3M 1.70G 1.70G 2M
utoo-npm 104.8K 52.6K 989M 3M 1.70G 1.70G 2M
utoo 52.1K 37.9K 990M 3M 1.70G 1.70G 2M

p4_warm_link

PM wall ±σ user sys RSS pgMinor
bun 3.10s 0.02s 0.19s 2.37s 134M 33.3K
utoo-next 2.25s 0.07s 0.47s 3.82s 78M 18.3K
utoo-npm 2.08s 0.06s 0.46s 3.76s 78M 18.7K
utoo 2.03s 0.07s 0.34s 3.31s 50M 11.0K
PM vCtx iCtx netRX netTX cache node_mod lock
bun 260 21 5M 15K 1.91G 1.73G 1M
utoo-next 41.9K 19.4K 2K 11K 1.70G 1.70G 2M
utoo-npm 41.3K 18.9K 1K 6K 1.70G 1.70G 2M
utoo 7.5K 4.5K 1K 4K 1.71G 1.70G 2M

npmmirror.com: no output captured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Pkg Manager Area: Package Manager benchmark Run pm-bench on PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant