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

[Fiber] Track Event Time, startTransition Time and setState Time #31008

Merged
merged 9 commits into from
Sep 20, 2024

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Sep 20, 2024

This tracks the current window.event.timeStamp the first time we setState or call startTransition. For either the blocking track or transition track. We can use this to show how long we were blocked by other events or overhead from when the user interacted until we got called into React.

Then we track the time we start awaiting a Promise returned from startTransition. We can use this track how long we waited on an Action to complete before setState was called.

Then finally we track when setState was called so we can track how long we were blocked by other word before we could actually start rendering. For a Transition this might be blocked by Blocking React render work.

We only log these once a subsequent render actually happened. If no render was actually scheduled, then we don't log these. E.g. if an isomorphic Action doesn't call startTransition there's no render so we don't log it.

We only log the first event/update/transition even if multiple are batched into it later. If multiple Actions are entangled they're all treated as one until an update happens. If no update happens and all entangled actions finish, we clear the transition so that the next time a new sequence starts we can log it.

We also clamp these (start the track later) if they were scheduled within a render/commit. Since we share a single track we don't want to create overlapping tracks.

The purpose of this is not to show every event/action that happens but to show a prelude to how long we were blocked before a render started. So you can follow the first event to commit.

Screenshot 2024-09-20 at 1 59 58 AM

I still need to add the rendering/suspended phases to the timeline which why this screenshot has a gap.

Screenshot 2024-09-20 at 12 50 27 AM

In this case it's a Form Action which started a render into the form which then suspended on the action. The action then caused a refresh, which interrupts with its own update that's blocked before rendering. Suspended roots like this is interesting because we could in theory start working on a different root in the meantime which makes this timeline less linear.

We don't track all scheduled updates but only the explicit ones like setState.
Copy link

vercel bot commented Sep 20, 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 Sep 20, 2024 6:13am

…nsition

This indicates the time we were blocked by something else before we could
process the user input.
The internal version doesn't log its time as an update.
I.e. the currently on-going render was the same track.
More times read now
@react-sizebot
Copy link

Comparing: e495392...84c2d11

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.82 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.08% 508.22 kB 508.62 kB +0.04% 90.95 kB 90.98 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 +0.08% 513.15 kB 513.56 kB +0.04% 91.67 kB 91.70 kB
facebook-www/ReactDOM-prod.classic.js +0.07% 602.57 kB 603.01 kB +0.04% 106.64 kB 106.69 kB
facebook-www/ReactDOM-prod.modern.js +0.07% 578.84 kB 579.24 kB +0.03% 102.76 kB 102.79 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 +1.35% 414.15 kB 419.76 kB +1.24% 67.78 kB 68.62 kB
oss-experimental/react-dom/cjs/react-dom-profiling.profiling.js +0.99% 542.34 kB 547.69 kB +0.97% 96.65 kB 97.59 kB
oss-experimental/react-art/cjs/react-art.development.js +0.96% 561.74 kB 567.16 kB +0.88% 91.04 kB 91.84 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js +0.90% 643.25 kB 649.02 kB +0.90% 103.46 kB 104.39 kB
oss-experimental/react-dom/cjs/react-dom-client.development.js +0.62% 946.27 kB 952.13 kB +0.61% 160.23 kB 161.20 kB
oss-experimental/react-dom/cjs/react-dom-profiling.development.js +0.61% 962.71 kB 968.57 kB +0.60% 163.05 kB 164.03 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js +0.61% 963.21 kB 969.06 kB +0.59% 164.05 kB 165.02 kB
oss-stable-rc/react-noop-renderer/cjs/react-noop-renderer.production.js +0.43% 35.27 kB 35.43 kB +0.36% 6.65 kB 6.67 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.production.js +0.43% 35.27 kB 35.43 kB +0.36% 6.65 kB 6.67 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.production.js +0.43% 35.29 kB 35.45 kB +0.34% 6.68 kB 6.70 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.production.js +0.43% 35.30 kB 35.46 kB +0.34% 6.68 kB 6.70 kB
oss-stable-rc/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.43% 35.40 kB 35.55 kB +0.36% 6.67 kB 6.69 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.43% 35.40 kB 35.55 kB +0.36% 6.67 kB 6.69 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.43% 35.42 kB 35.58 kB +0.31% 6.69 kB 6.72 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.production.js +0.43% 35.43 kB 35.59 kB +0.33% 6.70 kB 6.72 kB
oss-stable-rc/react-noop-renderer/cjs/react-noop-renderer.development.js +0.42% 39.40 kB 39.56 kB +0.33% 7.24 kB 7.26 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.development.js +0.42% 39.40 kB 39.56 kB +0.33% 7.24 kB 7.26 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.development.js +0.42% 39.42 kB 39.58 kB +0.30% 7.26 kB 7.29 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.development.js +0.42% 39.43 kB 39.59 kB +0.30% 7.27 kB 7.29 kB
oss-stable-rc/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.42% 39.54 kB 39.70 kB +0.33% 7.25 kB 7.28 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.42% 39.54 kB 39.70 kB +0.33% 7.25 kB 7.28 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.42% 39.56 kB 39.72 kB +0.30% 7.28 kB 7.30 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +0.42% 39.57 kB 39.73 kB +0.30% 7.29 kB 7.31 kB

Generated by 🚫 dangerJS against ed217fc

@sebmarkbage sebmarkbage merged commit d4688df into facebook:main Sep 20, 2024
184 checks passed
github-actions bot pushed a commit that referenced this pull request Sep 20, 2024
)

This tracks the current window.event.timeStamp the first time we
setState or call startTransition. For either the blocking track or
transition track. We can use this to show how long we were blocked by
other events or overhead from when the user interacted until we got
called into React.

Then we track the time we start awaiting a Promise returned from
startTransition. We can use this track how long we waited on an Action
to complete before setState was called.

Then finally we track when setState was called so we can track how long
we were blocked by other word before we could actually start rendering.
For a Transition this might be blocked by Blocking React render work.

We only log these once a subsequent render actually happened. If no
render was actually scheduled, then we don't log these. E.g. if an
isomorphic Action doesn't call startTransition there's no render so we
don't log it.

We only log the first event/update/transition even if multiple are
batched into it later. If multiple Actions are entangled they're all
treated as one until an update happens. If no update happens and all
entangled actions finish, we clear the transition so that the next time
a new sequence starts we can log it.

We also clamp these (start the track later) if they were scheduled
within a render/commit. Since we share a single track we don't want to
create overlapping tracks.

The purpose of this is not to show every event/action that happens but
to show a prelude to how long we were blocked before a render started.
So you can follow the first event to commit.

<img width="674" alt="Screenshot 2024-09-20 at 1 59 58 AM"
src="https://github.com/user-attachments/assets/151ba9e8-6b3c-4fa1-9f8d-e3602745eeb7">

I still need to add the rendering/suspended phases to the timeline which
why this screenshot has a gap.

<img width="993" alt="Screenshot 2024-09-20 at 12 50 27 AM"
src="https://github.com/user-attachments/assets/155b6675-b78a-4a22-a32b-212c15051074">

In this case it's a Form Action which started a render into the form
which then suspended on the action. The action then caused a refresh,
which interrupts with its own update that's blocked before rendering.
Suspended roots like this is interesting because we could in theory
start working on a different root in the meantime which makes this
timeline less linear.

DiffTrain build for commit d4688df.
github-actions bot pushed a commit that referenced this pull request Sep 20, 2024
)

This tracks the current window.event.timeStamp the first time we
setState or call startTransition. For either the blocking track or
transition track. We can use this to show how long we were blocked by
other events or overhead from when the user interacted until we got
called into React.

Then we track the time we start awaiting a Promise returned from
startTransition. We can use this track how long we waited on an Action
to complete before setState was called.

Then finally we track when setState was called so we can track how long
we were blocked by other word before we could actually start rendering.
For a Transition this might be blocked by Blocking React render work.

We only log these once a subsequent render actually happened. If no
render was actually scheduled, then we don't log these. E.g. if an
isomorphic Action doesn't call startTransition there's no render so we
don't log it.

We only log the first event/update/transition even if multiple are
batched into it later. If multiple Actions are entangled they're all
treated as one until an update happens. If no update happens and all
entangled actions finish, we clear the transition so that the next time
a new sequence starts we can log it.

We also clamp these (start the track later) if they were scheduled
within a render/commit. Since we share a single track we don't want to
create overlapping tracks.

The purpose of this is not to show every event/action that happens but
to show a prelude to how long we were blocked before a render started.
So you can follow the first event to commit.

<img width="674" alt="Screenshot 2024-09-20 at 1 59 58 AM"
src="https://github.com/user-attachments/assets/151ba9e8-6b3c-4fa1-9f8d-e3602745eeb7">

I still need to add the rendering/suspended phases to the timeline which
why this screenshot has a gap.

<img width="993" alt="Screenshot 2024-09-20 at 12 50 27 AM"
src="https://github.com/user-attachments/assets/155b6675-b78a-4a22-a32b-212c15051074">

In this case it's a Form Action which started a render into the form
which then suspended on the action. The action then caused a refresh,
which interrupts with its own update that's blocked before rendering.
Suspended roots like this is interesting because we could in theory
start working on a different root in the meantime which makes this
timeline less linear.

DiffTrain build for [d4688df](d4688df)
github-actions bot pushed a commit to zuwenyu/react that referenced this pull request Sep 23, 2024
…ebook#31008)

This tracks the current window.event.timeStamp the first time we
setState or call startTransition. For either the blocking track or
transition track. We can use this to show how long we were blocked by
other events or overhead from when the user interacted until we got
called into React.

Then we track the time we start awaiting a Promise returned from
startTransition. We can use this track how long we waited on an Action
to complete before setState was called.

Then finally we track when setState was called so we can track how long
we were blocked by other word before we could actually start rendering.
For a Transition this might be blocked by Blocking React render work.

We only log these once a subsequent render actually happened. If no
render was actually scheduled, then we don't log these. E.g. if an
isomorphic Action doesn't call startTransition there's no render so we
don't log it.

We only log the first event/update/transition even if multiple are
batched into it later. If multiple Actions are entangled they're all
treated as one until an update happens. If no update happens and all
entangled actions finish, we clear the transition so that the next time
a new sequence starts we can log it.

We also clamp these (start the track later) if they were scheduled
within a render/commit. Since we share a single track we don't want to
create overlapping tracks.

The purpose of this is not to show every event/action that happens but
to show a prelude to how long we were blocked before a render started.
So you can follow the first event to commit.

<img width="674" alt="Screenshot 2024-09-20 at 1 59 58 AM"
src="https://github.com/user-attachments/assets/151ba9e8-6b3c-4fa1-9f8d-e3602745eeb7">

I still need to add the rendering/suspended phases to the timeline which
why this screenshot has a gap.

<img width="993" alt="Screenshot 2024-09-20 at 12 50 27 AM"
src="https://github.com/user-attachments/assets/155b6675-b78a-4a22-a32b-212c15051074">

In this case it's a Form Action which started a render into the form
which then suspended on the action. The action then caused a refresh,
which interrupts with its own update that's blocked before rendering.
Suspended roots like this is interesting because we could in theory
start working on a different root in the meantime which makes this
timeline less linear.

DiffTrain build for commit facebook@d4688df.
github-actions bot pushed a commit to zuwenyu/react that referenced this pull request Sep 23, 2024
…ebook#31008)

This tracks the current window.event.timeStamp the first time we
setState or call startTransition. For either the blocking track or
transition track. We can use this to show how long we were blocked by
other events or overhead from when the user interacted until we got
called into React.

Then we track the time we start awaiting a Promise returned from
startTransition. We can use this track how long we waited on an Action
to complete before setState was called.

Then finally we track when setState was called so we can track how long
we were blocked by other word before we could actually start rendering.
For a Transition this might be blocked by Blocking React render work.

We only log these once a subsequent render actually happened. If no
render was actually scheduled, then we don't log these. E.g. if an
isomorphic Action doesn't call startTransition there's no render so we
don't log it.

We only log the first event/update/transition even if multiple are
batched into it later. If multiple Actions are entangled they're all
treated as one until an update happens. If no update happens and all
entangled actions finish, we clear the transition so that the next time
a new sequence starts we can log it.

We also clamp these (start the track later) if they were scheduled
within a render/commit. Since we share a single track we don't want to
create overlapping tracks.

The purpose of this is not to show every event/action that happens but
to show a prelude to how long we were blocked before a render started.
So you can follow the first event to commit.

<img width="674" alt="Screenshot 2024-09-20 at 1 59 58 AM"
src="https://github.com/user-attachments/assets/151ba9e8-6b3c-4fa1-9f8d-e3602745eeb7">

I still need to add the rendering/suspended phases to the timeline which
why this screenshot has a gap.

<img width="993" alt="Screenshot 2024-09-20 at 12 50 27 AM"
src="https://github.com/user-attachments/assets/155b6675-b78a-4a22-a32b-212c15051074">

In this case it's a Form Action which started a render into the form
which then suspended on the action. The action then caused a refresh,
which interrupts with its own update that's blocked before rendering.
Suspended roots like this is interesting because we could in theory
start working on a different root in the meantime which makes this
timeline less linear.

DiffTrain build for [d4688df](facebook@d4688df)
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