Commit 3f45941
authored
perf(install): improve parallelism of fetches during npm resolution (#32416)
disclosure: profiling and optimization idea by me, code changes (and the
rest of this PR description) by claude
Before
resolve_pending processes one parent node at a time sequentially. Inside
resolve_next_pending,
it uses FuturesOrdered to fetch package info for that single parent's
dependencies concurrently
— but there is no overlap between parents. If parent A has deps [x, y,
z] and parent B has
deps [p, q], we fetch x/y/z concurrently, wait for them all to be
processed, then move to B and
fetch p/q. Newly discovered children go to the back of the queue and
can't start fetching
until every previously-queued parent finishes.
After
drain_pending_parallel drains all pending parent nodes into a single
FuturesUnordered, so all
parents' dep fetches are in-flight simultaneously. Results are buffered
per-parent and retired
in FIFO order (by insertion order) to preserve deterministic resolution
— even though network
responses arrive out of order, we process parents in the same order the
old code would have.
When a parent is retired and its deps are processed, any newly
discovered child nodes are
immediately enqueued into the same FuturesUnordered. This means we don't
wait for the entire
current BFS level to complete before starting the next — child fetches
overlap with sibling
parent fetches, giving cross-BFS-level parallelism.
Results
---
```
Benchmark 1: /Users/nathanwhit/Documents/Code/deno/target/deno-baseline install
Time (mean ± σ): 8.295 s ± 0.879 s [User: 1.196 s, System: 3.599 s]
Range (min … max): 7.028 s … 9.758 s 10 runs
Benchmark 2: /Users/nathanwhit/Documents/Code/deno/target/release-lite/deno install
Time (mean ± σ): 3.342 s ± 0.344 s [User: 0.981 s, System: 3.297 s]
Range (min … max): 2.992 s … 4.138 s 10 runs
```1 parent 74cc882 commit 3f45941
1 file changed
Lines changed: 355 additions & 139 deletions
0 commit comments