Skip to content
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

Cache Execution Scope #6076

Merged
merged 1 commit into from
Jul 15, 2024
Merged

Conversation

seanparsons
Copy link
Contributor

Problem:
For Remix projects there's a lot of calls which create execution scopes multiple times per frame and even potentially for those multiple times for the same files as a result of them being nested.

Fix:
I added a very simple caching scheme for the execution scopes which clears the entire cache if a new projectContents is seen and otherwise caches the entire result if building the scope by file. This has taken a block that could take around 18ms down to a seeming maximum of 6ms.

Before:
Before

After:
After

Commit Details:

  • createExecutionScope caches the scopes by filename and the project contents as a whole.

Manual Tests:
I hereby swear that:

  • I opened a hydrogen project and it loaded
  • I could navigate to various routes in Preview mode

Fixes #6064

- `createExecutionScope` caches the scopes by filename and the
  project contents as a whole.
Copy link
Contributor

github-actions bot commented Jul 12, 2024

Try me

Copy link

relativeci bot commented Jul 12, 2024

#13365 Bundle Size — 62.65MiB (~+0.01%).

5388ec8(current) vs 6339ece master#13362(baseline)

Warning

Bundle contains 70 duplicate packages – View duplicate packages

Bundle metrics  Change 2 changes Regression 1 regression
                 Current
#13365
     Baseline
#13362
Regression  Initial JS 45.72MiB(~+0.01%) 45.72MiB
No change  Initial CSS 0B 0B
Change  Cache Invalidation 21.56% 21.54%
No change  Chunks 31 31
No change  Assets 34 34
No change  Modules 4371 4371
No change  Duplicate Modules 521 521
No change  Duplicate Code 31.68% 31.68%
No change  Packages 469 469
No change  Duplicate Packages 70 70
Bundle size by type  Change 2 changes Regression 1 regression Improvement 1 improvement
                 Current
#13365
     Baseline
#13362
Regression  JS 62.63MiB (~+0.01%) 62.63MiB
Improvement  HTML 11.16KiB (-0.33%) 11.2KiB

Bundle analysis reportBranch performance/cache-execution-scop...Project dashboard

@seanparsons seanparsons merged commit 29617cb into master Jul 15, 2024
17 checks passed
@seanparsons seanparsons deleted the performance/cache-execution-scope branch July 15, 2024 09:45
balazsbajorics added a commit that referenced this pull request Jul 19, 2024
**Problem:**
When anything in the projectContents changes, the DerivedState.remixData
gets recreated. (This should be improved to only recreate the remixData
if we actually change the file-based routing)

The `UtopiaRemixRootComponent` uses **illegal** (🙂) useEditorState hooks
to access `DerivedState.remixData`.

Since `DerivedState.remixData` is referentially new, the useEditorState
hooks will trigger a re-render of every UtopiaRemixRootComponent.

The UtopiaRemixRootComponent rerenders then basically trigger an almost
full rerender of the canvas before the "real" canvas rerender step.

on master:
<img width="1097" alt="image"
src="https://github.com/user-attachments/assets/d15c8a69-0bbc-47de-be08-c896b8e70f1c">
with Sean's createExecutionScope cache fix (currently disabled and
blocked by #6091):
<img width="849" alt="image"
src="https://github.com/user-attachments/assets/e649e8da-8b1b-43f7-b207-927d67bcfbbf">

On the image you can see that in the sample store's `/` route this takes
15ms every single frame.

**Fix:**
**20ms -> 10ms -> 5ms**
<img width="885" alt="image"
src="https://github.com/user-attachments/assets/c78e1ec7-993f-4bc7-b109-8030bd649e5c">
When the canvas is in selective rerender mode, DO NOT let
`UtopiaRemixRootComponent` rerender itself. Not updating
UtopiaRemixRootComponent during the selective mode should be safe, since
the continuous canvas interactions never cause the file based routing or
loaders etc to update.

**Commit Details:** (< vv pls delete this section if's not relevant)

- Wrapping the canvas in a EditorStateContext provider with the value
forced to `null` which means we will throw an error in the future every
time new code accidentally uses the useEditorState hooks (which are
_not_ compatible with selective re-rendering). Hopefully this means
selective re-rendering will be less brittle in the future, but in a
follow up PR I will write tests for this too
- Added new hook `useCanvasState` which is almost the same as
`useEditorState` except it takes an extra callback `allowRerender`. If
AllowRerender is false, then no matter what changes in the editor state,
we will passively reject the component update and the hook will return
the _old_ state value.
- Using the new hook in `utopia-remix-root-component`
- Profit!

**Notes:**
This PR depends on #6091 because the selective re-rendering of the remix
root component causes the same css issue as Sean's original #6076

**Manual Tests:**
I hereby swear that:

- [x] I opened a hydrogen project and it loaded
- [x] I could navigate to various routes in Preview mode
liady pushed a commit that referenced this pull request Dec 13, 2024
- `createExecutionScope` caches the scopes by filename and the project
contents as a whole.
liady pushed a commit that referenced this pull request Dec 13, 2024
**Problem:**
When anything in the projectContents changes, the DerivedState.remixData
gets recreated. (This should be improved to only recreate the remixData
if we actually change the file-based routing)

The `UtopiaRemixRootComponent` uses **illegal** (🙂) useEditorState hooks
to access `DerivedState.remixData`.

Since `DerivedState.remixData` is referentially new, the useEditorState
hooks will trigger a re-render of every UtopiaRemixRootComponent.

The UtopiaRemixRootComponent rerenders then basically trigger an almost
full rerender of the canvas before the "real" canvas rerender step.

on master:
<img width="1097" alt="image"
src="https://github.com/user-attachments/assets/d15c8a69-0bbc-47de-be08-c896b8e70f1c">
with Sean's createExecutionScope cache fix (currently disabled and
blocked by #6091):
<img width="849" alt="image"
src="https://github.com/user-attachments/assets/e649e8da-8b1b-43f7-b207-927d67bcfbbf">

On the image you can see that in the sample store's `/` route this takes
15ms every single frame.

**Fix:**
**20ms -> 10ms -> 5ms**
<img width="885" alt="image"
src="https://github.com/user-attachments/assets/c78e1ec7-993f-4bc7-b109-8030bd649e5c">
When the canvas is in selective rerender mode, DO NOT let
`UtopiaRemixRootComponent` rerender itself. Not updating
UtopiaRemixRootComponent during the selective mode should be safe, since
the continuous canvas interactions never cause the file based routing or
loaders etc to update.

**Commit Details:** (< vv pls delete this section if's not relevant)

- Wrapping the canvas in a EditorStateContext provider with the value
forced to `null` which means we will throw an error in the future every
time new code accidentally uses the useEditorState hooks (which are
_not_ compatible with selective re-rendering). Hopefully this means
selective re-rendering will be less brittle in the future, but in a
follow up PR I will write tests for this too
- Added new hook `useCanvasState` which is almost the same as
`useEditorState` except it takes an extra callback `allowRerender`. If
AllowRerender is false, then no matter what changes in the editor state,
we will passively reject the component update and the hook will return
the _old_ state value.
- Using the new hook in `utopia-remix-root-component`
- Profit!

**Notes:**
This PR depends on #6091 because the selective re-rendering of the remix
root component causes the same css issue as Sean's original #6076

**Manual Tests:**
I hereby swear that:

- [x] I opened a hydrogen project and it loaded
- [x] I could navigate to various routes in Preview mode
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.

Canvas Performance: getRemixExportsOfModule calls createExecutionScope a lot
4 participants