Repository navigation
fix(signals): a projection's reader pulls the derive it reads through (#4782) - #4796
Conversation
…#4782) pullFamily's settled branch read the derive untracked, which wakes a lazy node but does not refresh a stale one, and a leaf carries no height from its derive. A projection whose derive sits higher (it reads a memo) was read stale by a lower projection, which then ran again: O(N^2) per flush since #3774. The pull now makes the pull a tracked read makes: the derive brought up to date, the reader lifted above it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_0117BoWNSSgtemsSYsaX2hXE
🦋 Changeset detectedLatest commit: 7817955 The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Size (brotli, eager entry chunk)
|
Coverage Report for CI Build 43189861931Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage remained the same at 78.945%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will degrade performance by 5.19%2 warnings
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
Fixes #4782.
What
A projection
Bwhose derive reads the leaves of another projectionAcould run beforeAre-derived in the same flush. This happens whenA's derive sits higher in the heap, for example because it reads a memo.Bcomputed overA's previous answer,Are-derived, andBran again. A projectionRover N suchBs re-ran for each lateA, so the flush was O(N²). The reporter's 10,000-node mount went from 2.3 s on rc.13 to 17.5 s on rc.21. This regressed in #3774.Fix
pullFamily's settled branch read the derive untracked. An untrackedreadonly wakes a lazy or dormant node (prepareComputed(el, false)). It does not refresh a stale one, and a store leaf has no_fn, so its reader never took a height from the derive. That branch now makes the same pull a tracked read of a memo makes (pullComputed(fw, reader)). The derive is brought up to date before any leaf is served, and the reader is lifted above it, so later flushes order it after the derive. It does this without linking, as before.The pull is ordering only. The F-6 posture handoff and the #4491 stale-reader mark that follow a tracked read are untouched.
This is the reporter's experiment, adopted after checking it against the rules.
Rules checked
BreadAbehind its input, which is the bug.Size (local, brotli, against next @ dc33de6)
+ createStore: +12 BTests
packages/signals/tests/projection-reads-projection-4782.test.ts: the issue's shape at N=50, with the derive reading a memo and reading store keys only. EachBruns once andRonce. Onnextthe memo case gives 98Bruns and 49Rruns.Generated by Claude Code