Skip to content

fix: always mark reactions of deriveds #16457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 20, 2025
Merged

fix: always mark reactions of deriveds #16457

merged 4 commits into from
Jul 20, 2025

Conversation

Rich-Harris
Copy link
Member

This was absolute hell to isolate. Essentially: if a derived is read inside a time-travelling batch, it isn't (and can't) be marked clean afterwards, which means that if one of its dependencies later becomes dirty, reactions of the derived are not notified.

I was worried that this would impact performance, but surprisingly this appears to be faster:

sbench_create_signals
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  355.59ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 371.42ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼   146.73ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 164.07ms
sbench_create_0to1
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  5.48ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 5.65ms
sbench_create_1to1
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 20.83ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 20.61ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.99ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.92ms
sbench_create_2to1
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 17.97ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 18.11ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.86ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.91ms
sbench_create_4to1
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 16.53ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 16.52ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.98ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  2.89ms
sbench_create_1000to1
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 15.04ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 14.89ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.98ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.95ms
sbench_create_1to2
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  9.71ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 10.05ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  0.74ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 0.78ms
sbench_create_1to4
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 7.99ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 8.03ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  0.51ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 0.53ms
sbench_create_1to8
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 6.39ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 6.31ms
sbench_create_1to1000
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 8.28ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 8.20ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼    0.64ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 0.75ms
kairo_avoidable_owned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  499.85ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 513.63ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 36.75ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  35.70ms
kairo_avoidable_unowned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 595.38ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 598.50ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 37.01ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 37.42ms
kairo_broad_owned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 465.94ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 470.34ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1.75ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1.79ms
kairo_broad_unowned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 462.52ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 467.32ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  1.77ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1.83ms
kairo_deep_owned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 202.65ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 203.98ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  1.63ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1.75ms
kairo_deep_unowned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 967.05ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 947.95ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  1.85ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1.93ms
kairo_diamond_owned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 426.73ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  412.08ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 19.96ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 20.47ms
kairo_diamond_unowned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 502.98ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 505.05ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 20.66ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  19.76ms
kairo_triangle_owned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 133.38ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  125.24ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.41ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.48ms
kairo_triangle_unowned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 246.48ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 245.34ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.71ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  3.55ms
kairo_mux_owned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  333.00ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 345.37ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.57ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.60ms
kairo_mux_unowned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 483.08ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 486.17ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.72ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2.69ms
kairo_repeated_owned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 77.44ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 77.77ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.12ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  3.00ms
kairo_repeated_unowned
  time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 75.53ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 75.86ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  3.13ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.23ms
kairo_unstable_owned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 117.65ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 114.97ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.54ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.54ms
kairo_unstable_unowned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 131.37ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 129.36ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.63ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 3.65ms
mol_bench_owned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 289.11ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 285.32ms
  gc_time: fastest is a (fix-batch-deriveds)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  0.91ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 0.94ms
mol_bench_unowned
  time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 307.17ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 303.50ms
  gc_time: fastest is b (main)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 0.91ms
    b: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼  0.85ms

I can only assume that having extra recursion in a tiny minority of cases is outweighed by having fewer bitwise operations in all other cases.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

Copy link

changeset-bot bot commented Jul 20, 2025

🦋 Changeset detected

Latest commit: 1dd5808

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Patch

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

Copy link
Contributor

Playground

pnpm add https://pkg.pr.new/svelte@16457

@paoloricciuti
Copy link
Member

Closes #16090
Closes #16104
Closes #16294

Weirdly it doesn't fix #15888 which seems to be almost the same bug

Copy link
Member

@paoloricciuti paoloricciuti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will close a lot of bugs so clearly there's something wrong...and I've been banging my head on this for quite a lot times and everytime i stop because I don't know how to fix it without extra rerunning.

Last time with #16110 @dummdidumm was a bit worried about GCTime but maybe it was just a flaky bench? So maybe it's worth merging and worry about eventual performance later since obviusly it's causing a lot of bugs.

@Rich-Harris Rich-Harris merged commit d3a01bd into main Jul 20, 2025
15 checks passed
@Rich-Harris Rich-Harris deleted the fix-batch-deriveds branch July 20, 2025 21:19
This was referenced Jul 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy