Skip to content

Conversation

@josephsavona
Copy link
Member

@josephsavona josephsavona commented May 18, 2024

Stack from ghstack (oldest at bottom):

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was t0, we'd look for the instruction where t0 was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

[ghstack-poisoned]
@vercel
Copy link

vercel bot commented May 18, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 23, 2024 0:12am

josephsavona added a commit that referenced this pull request May 18, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: 22e4960
Pull Request resolved: #29157
@facebook-github-bot facebook-github-bot added the React Core Team Opened by a member of the React Core Team label May 18, 2024
@react-sizebot
Copy link

react-sizebot commented May 18, 2024

Comparing: bf046e8...6d4f5c8

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.66 kB 6.66 kB = 1.82 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 495.71 kB 495.71 kB = 88.78 kB 88.78 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.67 kB 6.67 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 500.51 kB 500.51 kB = 89.47 kB 89.47 kB
facebook-www/ReactDOM-prod.classic.js = 592.86 kB 592.86 kB = 104.28 kB 104.28 kB
facebook-www/ReactDOM-prod.modern.js = 569.08 kB 569.08 kB = 100.69 kB 100.69 kB
test_utils/ReactAllWarnings.js Deleted 64.35 kB 0.00 kB Deleted 16.05 kB 0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
test_utils/ReactAllWarnings.js Deleted 64.35 kB 0.00 kB Deleted 16.05 kB 0.00 kB

Generated by 🚫 dangerJS against 6d4f5c8

…r merging"

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 18, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: 675de0f
Pull Request resolved: #29157
@josephsavona josephsavona marked this pull request as draft May 18, 2024 00:23
…r merging"

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 20, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: 6085abe
Pull Request resolved: #29157
…r merging"

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 20, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: ab46a9e
Pull Request resolved: #29157
…r merging"

In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 20, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: b2b2791
Pull Request resolved: #29157
…r merging"


In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

NOTE: marking as draft because i have not yet verified all the fixtures changes (including checking that they are all have a snap fixture)

[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 20, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: f36a92a
Pull Request resolved: #29157
@josephsavona josephsavona marked this pull request as ready for review May 20, 2024 22:06
…r merging"


In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.


[ghstack-poisoned]
josephsavona added a commit that referenced this pull request May 21, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: 07d02d8
Pull Request resolved: #29157
Comment on lines +517 to +519
return [...scopeBlock.scope.declarations].some(([, decl]) =>
isAlwaysInvalidatingType(decl.identifier.type)
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Haven't spent time trying to find a case in which this is an issue, but note that this also affects scopes that produce a "always-invalidating" type transitively, from a nested scope:

In this example, it seems that both scopes @0 and @1 are now "eligble for merging". It looks like the inner decl isn't always guaranteed to invalidate on outer_dep changes though. Maybe I'm missing something though

scope @0 deps=[inner_dep, outer_dep] decls=[inner, outer] {
  outer = makeValue(outer_dep);
  scope@1 deps=[inner_dep] decls=[inner] {
    inner = {inner_dep};
  }
  maybeWrite(outer);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Interesting, i wasn't thinking about the nested case (more on that later) but about the transitive case. Something like: two values get merged into a single scope eg due to interleaving, x depends on a, y depends on b. Then some later value only depends on eg x, but that means it implicitly resets on changes to b as well:

scope @0 deps=[a, b] decls=[x, y] {
  // imagine this
  x = Array [  ]  
  y = Array [  ]
  x.push( a )
  y.push( b ) 
}
scope @1 deps=[y] decls=[z] {
  z = makeValue( y )
}

With this PR we'd now merge these scopes, and z will reset on changes to a even though y doesn't strictly depend on a. But...even if we didn't merge the scopes, y would still reset on changes to a, which would invalidate z anyway. So merging doesn't change the reset.

For the case you pointed out: the only way to have a subsequent scope depend on a value produced by an inner scope (that i can think of) is something like this:

function Component({ a, b, c }) {
  const x = [];
  let y;
  if (a) {
    y = [b];
  }
  x.push(c);

  const z = [y];

  return [z, x];
}

note y is declared outside the if, making it available for the subsequent z = [y] reference. That instruction sees the result of a phi node (due to the reassignment), and we don't currently infer types for phi nodes. So in practice, this case would not yet get merged.

I'll add this as a test case so we can find regressions.

…r merging"


In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.


[ghstack-poisoned]
@josephsavona
Copy link
Member Author

Updated to add a test case confirming that the nested case memoizes as expected (ie does not inadvertently merge). I couldn't easily replicate that level of precision with useMemo, so i added a way to disable the non-forget execution in snap. This way we will get a test failure (not just a change to snapshot output) if we regress on the case you pointed out.

@josephsavona josephsavona merged commit 6d4f5c8 into gh/josephsavona/9/base May 23, 2024
josephsavona added a commit that referenced this pull request May 23, 2024
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging.

Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.

ghstack-source-id: 0e3e05f
Pull Request resolved: #29157
@josephsavona josephsavona deleted the gh/josephsavona/9/head branch May 23, 2024 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants