Commit d81d5ab
authored
Proof of concept: task eviction after snapshot for turbo-tasks-backend (#91790)
> **Note:** This is a **proof of concept** implementation. It is not yet
ready for production use.
## Summary
Implements memory eviction for the turbo-tasks engine. After a
persistence snapshot completes, tasks that are safe to remove are
evicted from in-memory storage and transparently restored from disk on
next access.
### Eviction levels
- **Full eviction**: Entire task removed from the in-memory map
(restored from disk on access). Only possible when the task has no
meaningful transient state (and other state is already on disk)
- **DataAndMeta eviction**: Both data and meta categories cleared, but
the task stays in the map to preserve transient state (e.g.
`current_session_clean`, aggregated session-clean counts).
- **DataOnly eviction**: Only data-category fields cleared; meta (graph
structure, output, dirty state) stays in memory.
- **MetaOnly eviction**: Only meta-category fields cleared; data stays
in memory.
Data and meta evictability are computed independently — if one category
is modified but the other is clean, the clean category can still be
dropped.
Eviction is gated behind `BackendOptions::evict_after_snapshot` (off by
default), and can be enabled in Next.js via the
`TURBO_ENGINE_EVICT_AFTER_SNAPSHOT=1` env var for testing.
## Key changes
- **Orthogonal eviction decision tree** (`storage_schema.rs`): Data and
meta evictability are computed independently. Full eviction additionally
requires no meaningful transient state (session-clean flags, aggregated
session-clean counts). Replaces the previous sequential bail-out
approach which was too aggressive on full eviction (losing transient
session state on leaf tasks) and not aggressive enough on partial
eviction (blocking all eviction when only one category was modified).
- **`drop_partial()` codegen** (`task_storage_macro.rs`): New generated
methods to drop data
- **`restore_from_*()` codegen changes** (`task_storage_macro.rs`): New
semantics for merging persistent data from the backend with transient
data stored in memory.
- **`task_cache` moved into `Storage`** (`storage.rs`): The
`CachedTaskType → TaskId` deduplication map was previously a separate
field on `TurboTasksBackendInner`. It is now owned by `Storage` so
eviction can remove entries when a task is fully evicted. Because
`task_cache` is a pure performance cache (entries are re-populated by
`task_by_type()` on miss once the task type is persisted to backing
storage), evicting entries is safe. After bulk eviction the map is
shrunk when it is less than half full.
- **Parallel shard eviction** (`storage.rs`): Eviction iterates all
storage shards in parallel after snapshot, applying the appropriate
eviction level per task. Each shard is shrunk after bulk eviction to
reclaim slack capacity.
- In principle this is O(N) work to scan, but because each pass drops
>98% of tasks there isn't wasted work and the logic is fast, taking
<100ms for even the largest applications.
## Design notes
- **SessionDependent tasks**: SessionDependent tasks can still be
evicted but if `current_session_clean` is set we prevent full eviction
to avoid rechecking. Within a session the file-watchers are responsible
for invalidations after setting `current_session_clean`.
## Known limitations (proof of concept)
- No LRU or access-frequency tracking — all eligible tasks are evicted
on every snapshot cycle
- No memory pressure feedback — eviction runs on a timer, not in
response to actual memory pressure
- Only runs after snapshotting which tends to be a high point in memory
- Future work will explore interleaving this logic with snapshotting to
trim the peak
<!-- NEXT_JS_LLM_PR -->1 parent ed9a295 commit d81d5ab
34 files changed
Lines changed: 2989 additions & 407 deletions
File tree
- crates
- next-api/src
- next-napi-bindings/src/next_api
- test/e2e/filesystem-cache
- turbopack/crates
- turbo-persistence/src
- turbo-tasks-auto-hash-map/src
- turbo-tasks-backend
- src
- backend
- operation
- utils
- tests
- turbo-tasks-fetch/tests
- turbo-tasks-fs/src
- turbo-tasks-macros-tests/tests
- turbo-tasks-macros/src
- derive
- turbo-tasks-malloc/src
- turbo-tasks-testing
- src
- turbo-tasks/src
- turbopack-analyze/tests
- turbopack-node/tests
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1495 | 1495 | | |
1496 | 1496 | | |
1497 | 1497 | | |
1498 | | - | |
1499 | | - | |
| 1498 | + | |
| 1499 | + | |
1500 | 1500 | | |
1501 | 1501 | | |
1502 | 1502 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
256 | 256 | | |
257 | 257 | | |
258 | 258 | | |
| 259 | + | |
| 260 | + | |
259 | 261 | | |
260 | 262 | | |
261 | 263 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
619 | 619 | | |
620 | 620 | | |
621 | 621 | | |
622 | | - | |
623 | | - | |
| 622 | + | |
624 | 623 | | |
625 | 624 | | |
626 | 625 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
100 | 108 | | |
101 | 109 | | |
102 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
68 | 69 | | |
69 | 70 | | |
70 | 71 | | |
| 72 | + | |
71 | 73 | | |
72 | 74 | | |
73 | 75 | | |
| |||
0 commit comments