next.js
c5f0da7b - [turbopack] Remove turbotask functions from `trait ResolveOrigin` (#94324)

Commit
44 days ago
[turbopack] Remove turbotask functions from `trait ResolveOrigin` (#94324) ### What? Removes the `#[turbo_tasks::function]` annotations from the `ResolveOrigin` trait methods (`origin_path`, `asset_context`, `resolve_options`), turning them into plain synchronous trait methods. Callers obtain the value once via `Vc::into_trait_ref().await?` and then call the methods directly on the resulting `TraitRef`. This mirrors the earlier de-functionification of the `Issue` trait (#92623). ### Why? The `ResolveOrigin` implementations are all trivial — they return a stored field or delegate a single call. | Task (misses, before → after) | Misses removed | | --- | --- | | `ResolveOrigin::resolve_options` (dyn) | 92,608 → 0 | | `EcmascriptModuleAsset::origin_path` | 64,779 → 0 | | `ResolveOriginWithTransition::asset_context` | 52,292 → 0 | | `ResolveOriginWithTransition::origin_path` | 52,292 → 0 | | `EcmascriptModuleAsset::asset_context` | 41,164 → 0 | | `PlainResolveOrigin::{origin_path, asset_context}` | 105 + 105 → 0 | | `EcmascriptCssModule::{origin_path, asset_context}` | 32 + 32 → 0 | | `CssModule::{origin_path, asset_context}` | 19 + 19 → 0 | Net effect in that run: **~303k fewer cache misses** (total misses 6,197,068 → 5,893,545) — The ~1.35M eliminated cached-task *hits* additionally remove the per-call task lookup/scheduling overhead. The caching that genuinely matters is preserved one layer down — `AssetContext::resolve_options` (which `ResolveOrigin::resolve_options` delegated to) is still a cached task; its miss count is unchanged (39,668) since those distinct results were always computed, and it simply absorbs the call volume directly now (hit rate 57% → 92%). ## Build Performance: `ResolveOrigin` optimization Benchmark across 10 runs per branch. | Metric | Base | This branch | Δ | |---|---|---|---| | **Wall time** | 43.302 s | 42.692 s | **−0.61 s (−1.4%)** | | **User time** | 314.249 s | 310.919 s | **−3.33 s (−1.1%)** | | **Sys time** | 84.225 s | 84.618 s | +0.39 s (+0.5%) | | **MaxRSS** | 14106.1 MB | 13883.4 MB | **−222.8 MB (−1.6%)** | ### Notes on significance - **User time** is the cleanest signal: −1.1% with very tight variance (base σ 0.4%, branch σ 0.3%). The drop (~3.3 s) is well outside the noise — a real reduction in CPU work. - **MaxRSS** is down a solid 1.6% (~223 MB) with tight variance on both sides (σ ≈ 0.5–0.6%) — a clear, reproducible memory win. - **Wall time** improves 1.4%, but variance is large (base σ 6.6%, branch σ 4.5%, with one 50 s outlier in the base set), so treat this as directional. It tracks the user-time improvement. - **Sys time** is essentially flat (+0.5%, within its ~10% run-to-run noise) — no meaningful change, as expected for a CPU/allocation optimization. ### Invalidation tradeoff The main behavioral risk is invalidation granularity. Removing the per-method tasks removes their invalidation boundary: a consumer that previously depended only on the `origin_path()` (or `asset_context()`) task output now reads the value off the origin directly, so it is tied to the origin cell rather than to that one method's cached output. In practice this is narrow, because every `ResolveOrigin` implementor is an immutable, content-addressed `#[turbo_tasks::value]` (only `ResolvedVc`/owned fields) — a different field value means a different cell, so "reading the whole value vs. one field" does not by itself widen invalidation. <!-- NEXT_JS_LLM_PR -->
Author
Parents
Loading