Finding
notifySubscribers in src/index.ts (lines 50-53) swaps pendingSubscribers with a fresh new Set() on every iteration of the flush loop:
while (pendingSubscribers.size > 0) {
const subscribers = pendingSubscribers
pendingSubscribers = new Set()
// ...
}
When effects trigger further state writes (cascading updates), the while loop runs multiple iterations, each allocating a new Set.
Impact
GC pressure from short-lived Set allocations under cascading-update workloads. In the benchmarked derive chain scenario (depth 10, 1000 iterations), this means thousands of throwaway Sets per batch.
Proposed fix
Clear and reuse instead of allocating. Swap the reference, then call .clear() on the consumed Set so it can be reused on the next iteration. Alternatively, use a double-buffer pattern with two pre-allocated Sets.
Benchmark before and after to confirm the improvement is real.
Source: out/report-performance.txt, Finding 2
Finding
notifySubscribersinsrc/index.ts(lines 50-53) swapspendingSubscriberswith a freshnew Set()on every iteration of the flush loop:When effects trigger further state writes (cascading updates), the while loop runs multiple iterations, each allocating a new Set.
Impact
GC pressure from short-lived Set allocations under cascading-update workloads. In the benchmarked derive chain scenario (depth 10, 1000 iterations), this means thousands of throwaway Sets per batch.
Proposed fix
Clear and reuse instead of allocating. Swap the reference, then call
.clear()on the consumed Set so it can be reused on the next iteration. Alternatively, use a double-buffer pattern with two pre-allocated Sets.Benchmark before and after to confirm the improvement is real.
Source:
out/report-performance.txt, Finding 2