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

Fix Overlapping "message" Bug in Performance Track #31528

Merged
merged 4 commits into from
Nov 14, 2024

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Nov 13, 2024

When you schedule a microtask from render or effect and then call setState (or ping) from there, the "event" is the event that React scheduled (which will be a postMessage). The event time of this new render will be before the last render finished.

We usually clamp these but in this scenario the update doesn't happen while a render is happening. Causing overlapping events.

Before:

Screenshot 2024-11-12 at 11 01 30 PM

Therefore when we finalize a render we need to store the end of the last render so when we a new update comes in later with an event time earlier than that, we know to clamp it.

There's also a special case here where when we enter the RootDidNotComplete or RootSuspendedWithDelay case we neither leave the root as in progress nor commit it. Those needs to finalize too. Really this should be modeled as a suspended track that we haven't added yet. That's the gap between "Blocked" and "message" below.

After:

Screenshot 2024-11-13 at 12 31 34 AM

I also fixed an issue where we may log the same event name multiple times if we're rendering more than once in the same event. In this case I just leave a blank trace between the last commit and the next update.

I also adding ignoring of the "message" event at all in these cases when the event is from React's scheduling itself.

Copy link

vercel bot commented Nov 13, 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 Nov 14, 2024 9:33pm

@react-sizebot
Copy link

react-sizebot commented Nov 13, 2024

Comparing: 4686872...5ce48b6

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.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 509.09 kB 509.09 kB = 91.00 kB 91.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 514.03 kB 514.03 kB = 91.71 kB 91.71 kB
facebook-www/ReactDOM-prod.classic.js = 588.71 kB 588.71 kB = 104.18 kB 104.18 kB
facebook-www/ReactDOM-prod.modern.js = 578.98 kB 578.98 kB = 102.59 kB 102.59 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js +0.28% 424.05 kB 425.23 kB +0.34% 69.13 kB 69.36 kB
oss-experimental/react-dom/cjs/react-dom-profiling.profiling.js +0.21% 551.71 kB 552.87 kB +0.23% 98.07 kB 98.29 kB

Generated by 🚫 dangerJS against d1d95a5

That way we can clamp a new update within the same event which otherwise
would have en event time before the old render.
This is a special case which ends with no on-going renders but also doesn't
commit. So we need to finalize the render so that we know that we can't.

This should probably be handled more like a suspended yield instead.
… the event

We do this by applying the clamp lazily and not resetting the event info between renders.
That way we can ignore this event when we log where an update happened.
@sebmarkbage sebmarkbage merged commit c13986d into facebook:main Nov 14, 2024
160 of 161 checks passed
github-actions bot pushed a commit that referenced this pull request Nov 14, 2024
When you schedule a microtask from render or effect and then call
setState (or ping) from there, the "event" is the event that React
scheduled (which will be a postMessage). The event time of this new
render will be before the last render finished.

We usually clamp these but in this scenario the update doesn't happen
while a render is happening. Causing overlapping events.

Before:

<img width="1229" alt="Screenshot 2024-11-12 at 11 01 30 PM"
src="https://github.com/user-attachments/assets/9652cf3b-b358-453c-b295-1239cbb15952">

Therefore when we finalize a render we need to store the end of the last
render so when we a new update comes in later with an event time earlier
than that, we know to clamp it.

There's also a special case here where when we enter the
`RootDidNotComplete` or `RootSuspendedWithDelay` case we neither leave
the root as in progress nor commit it. Those needs to finalize too.
Really this should be modeled as a suspended track that we haven't added
yet. That's the gap between "Blocked" and "message" below.

After:

<img width="1471" alt="Screenshot 2024-11-13 at 12 31 34 AM"
src="https://github.com/user-attachments/assets/b24f994e-9055-4b10-ad29-ad9b36302ffc">

I also fixed an issue where we may log the same event name multiple
times if we're rendering more than once in the same event. In this case
I just leave a blank trace between the last commit and the next update.

I also adding ignoring of the "message" event at all in these cases when
the event is from React's scheduling itself.

DiffTrain build for [c13986d](c13986d)
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.

4 participants