[pull] canary from vercel:canary - #1360
Merged
Merged
Conversation
Avoid spawning a worker thread to run turbopack The typical arguments for worker threads are that they isolate the JS heap and enable parallelism, but turbopack does both these things by default (native heap is isolated, the js deps are minor and have a lot of overlap with existing next server deps). There is also no substantial parallelism opportunity from worker threads that aren't immediately delivered by turbopacks execution model ## Benchmarks Measured with a paired A/B harness that alternates `head` and `base` builds so thermal drift and background load cancel out, discarding a warmup build per variant and clearing `.next` before each run. Both variants are the same commit except for this change. 35 paired iterations on a default `create-next-app` (App Router, TS), Node 20.11.1, Apple silicon. | Metric | this PR | canary | Diff | 95% CI | Wins | | --- | --- | --- | --- | --- | --- | | `next-build` total | 2478 ms | 2595 ms | **-117 ms (4.5%)** | [50, 183] | 30/35 | | `run-turbopack` | 1228 ms | 1335 ms | -107 ms (8.0%) | [62, 152] | 31/35 | | overhead (total - turbopack) | 1250 ms | 1260 ms | -10 ms (0.8%) | [-27, 46] | 20/35 | | wall clock | 2775 ms | 2888 ms | -112 ms (3.9%) | [45, 180] | 30/35 | | peak RSS | 1175 MiB | 1195 MiB | **-19 MiB (1.6%)** | [3.4, 35.3] | 22/35 | Significant by both a paired t-test and a Wilcoxon signed-rank test (p = 0.0001 for total build time, p = 0.025 for RSS). The Wilcoxon is included because a couple of slow builds per run would otherwise dominate the variance. Nearly all of the saving lands inside the `run-turbopack` span rather than around it, which is expected: that span wraps the worker spawn, the IPC to marshal the build across, and the teardown, so deleting the worker removes work from inside it. The win is proportionally smaller on larger apps, where compilation dominates. On `bench/basic-app` (~400 source modules, ~19s builds) the same ~115 ms is well inside the noise -- 12 paired iterations there showed no significant difference on any metric. So this is a real but small improvement that is only user-visible on small builds: | Metric | this PR | canary | Diff | 95% CI | | --- | --- | --- | --- | --- | | `next-build` total | 19313 ms | 19436 ms | -123 ms (0.6%) | [-256, 502] | | overhead (total - turbopack) | 1424 ms | 1415 ms | +9 ms (0.6% slower) | [-52, 70] | Caveats: single machine and two fixture shapes. Peak RSS is the build process's own footprint (`/usr/bin/time -l`), which includes the worker thread's isolate but not the separately spawned static-generation workers. A CI runner with fewer cores would plausibly show a larger effect.
Adds garbage collection, built on the `parent_count` reference counting
### How collection works
* we scan all storage shards for collectible tasks to seed the sweep
* For each collectible task we
1. mark it as deleted
2. remove all outgoing edges
3. queue new tasks for deletion if the edge removals triggered it
For removing edges we rely on the existing `CleanupOldEdges` operation,
though it is enhanced to collect the tasks that become collectible as
edges are removed
Deletion markers are transformed into tombstones by persistence and then
dropped from memory by eviction.
### Coordinator changes
GC mutates the graph, so we exclude other tasks from running while it
works. When gc completes we hand off to persistence which switches to
the existing copy on write mode.
The subtle piece is `GcPhase::into_snapshot`: GC has to hand its
exclusion directly to the snapshot that tombstones what it collected.
Swapping the flags under one lock leaves no window where an operation
could start and resurrect a just-collected task.
### Enabling it
Off by default; `TURBO_ENGINE_GC` turns it on, also requires eviction to
be enabled (otherwise deleted tasks persist in RAM)
`prevent_gc()` becomes real, pinning the calling task through
`transient_ref_count`.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )