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

[Flight][Fizz] tasks that ping in a microtask should render synchronously #28907

Closed
wants to merge 3 commits into from

Conversation

gnoff
Copy link
Collaborator

@gnoff gnoff commented Apr 25, 2024

stacked on #28900

This change modifies the ping mechanism for FlightServer and FizzServer to perform work synchronously if infer the ping is happening in a microtask. The heuristic is to consider whether we're already in a "work" phase which is only cleared in a second macrotask scheduled alongside the work task. If we are and the task is the only task in the queue we assume we're in a microtask and immediately retry the task.

There is an edge case however that I suspect can crop up where a ping is interleaved between a work task and the flush task. If this happens it will also appear like a microtask and be retried synchronously. While this isn't the intent of the PR this also isn't breaking any semantics so this should be fine.

I also updated the flight tests to use the same environment as FizzServer and stopped mocking setImmediate to run synchronously. This was necessary to actually exercise the timing here but it also better tests the Node implementation of FlightServer because it can't hide task scheduling mistakes behind synchronous execution

Today work that pings in a microtask in Flight and Fizz will end up being rendered in a new macrotask. This is potentially sub-optimal for cache-locality reasons but it also has an impact on flushing because flushes always happen synchronously after rendering. It would be ideal if tasks that can ping in a microtask get a chance to render before we flush because we can end up with a more compact wire format for flight and we can potentially avoid showing fallbacks for fizz.

This commit doesn't actually implement rendering in microtasks. This will come in a follow up change. What this change does do is refactor the flushing controls to be able to schedule flushing in a macrotask separately from the render phase. The appraoch uses a notion of epochs to allow scheduled work to infer if it is still valid. For instance if Float causes a flush to be enqueued but then the next task is a ping leading to a render we don't necessarily want to flush before additional renders are allowed to complete. Additionally if there is already a flush scheduled we don't want an enqueued flush from Float to lead to an additional flush.

the request's flushScheduled property is now more narrowly tailored to represent out-of-band flushes enqueued through float and not the general purpose flushing that is done after every work loop.

the request now has an epoch property which can be used to determine if we haven't started a new work loop or flush since the task was previously scheduled.

In some environments schedulWork is synchronous. All the logic still makes sense for synchronous work even if it can have unecessary overhead (such as checking if we're in the same epoch since this will necessarily be true in sync mode). However sync mode is mostly useful for legacy renderers like renderToString and we should probably move away from in for the browser build anyway so I don't think we ought to concern ourselves with further optimization of the sync case.
…usly

This change modifies the ping mechanism for FlightServer and FizzServer to perform work synchronously if infer the ping is happening in a microtask. The heuristic is to consider whether we're already in a "work" phase which is only cleared in a second macrotask scheduled alongside the work task. If we are and the task is the only task in the queue we assume we're in a microtask and immediately retry the task.

There is an edge case however that I suspect can crop up where a ping is interleaved between a work task and the flush task. If this happens it will also appear like a microtask and be retried synchronously. While this isn't the intent of the PR this also isn't breaking any semantics so this should be fine.
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 25, 2024
@react-sizebot
Copy link

Comparing: 6f18664...6c0f74a

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 = 497.71 kB 497.71 kB = 88.93 kB 88.93 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 504.00 kB 504.00 kB = 89.95 kB 89.95 kB
facebook-www/ReactDOM-prod.classic.js = 591.14 kB 591.14 kB = 103.91 kB 103.91 kB
facebook-www/ReactDOM-prod.modern.js = 566.95 kB 566.95 kB = 100.12 kB 100.12 kB
test_utils/ReactAllWarnings.js Deleted 64.67 kB 0.00 kB Deleted 16.09 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
oss-stable-semver/react-server/cjs/react-server-flight.development.js +0.98% 86.93 kB 87.78 kB +1.51% 20.22 kB 20.52 kB
oss-stable/react-server/cjs/react-server-flight.development.js +0.98% 86.93 kB 87.78 kB +1.51% 20.22 kB 20.52 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +0.75% 113.28 kB 114.13 kB +1.20% 24.82 kB 25.12 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.69% 123.70 kB 124.55 kB +1.07% 28.59 kB 28.90 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.69% 123.70 kB 124.55 kB +1.07% 28.59 kB 28.90 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.67% 126.61 kB 127.46 kB +1.06% 29.18 kB 29.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.67% 126.61 kB 127.46 kB +1.06% 29.18 kB 29.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.67% 127.51 kB 128.36 kB +1.01% 29.42 kB 29.71 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.67% 127.51 kB 128.36 kB +1.01% 29.42 kB 29.71 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.66% 129.06 kB 129.91 kB +0.98% 29.85 kB 30.14 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.66% 129.06 kB 129.91 kB +0.98% 29.85 kB 30.14 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.66% 129.44 kB 130.29 kB +1.01% 29.91 kB 30.21 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.66% 129.44 kB 130.29 kB +1.01% 29.91 kB 30.21 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.development.js +0.65% 129.86 kB 130.71 kB +1.05% 29.59 kB 29.90 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.development.js +0.65% 129.86 kB 130.71 kB +1.05% 29.59 kB 29.90 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.64% 132.15 kB 133.00 kB +1.02% 30.18 kB 30.48 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.64% 132.15 kB 133.00 kB +1.02% 30.18 kB 30.48 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.64% 132.50 kB 133.35 kB +1.00% 30.40 kB 30.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.64% 132.50 kB 133.35 kB +1.00% 30.40 kB 30.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.63% 134.79 kB 135.64 kB +0.98% 31.01 kB 31.32 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.63% 134.79 kB 135.64 kB +0.98% 31.01 kB 31.32 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.55% 153.60 kB 154.45 kB +0.87% 33.92 kB 34.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.54% 156.31 kB 157.16 kB +0.86% 34.45 kB 34.75 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.54% 157.88 kB 158.73 kB +0.83% 34.92 kB 35.21 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.54% 158.76 kB 159.61 kB +0.84% 35.12 kB 35.41 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.development.js +0.53% 159.76 kB 160.61 kB +0.86% 34.93 kB 35.24 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.53% 159.81 kB 160.66 kB +0.81% 35.42 kB 35.71 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.52% 162.05 kB 162.90 kB +0.82% 35.53 kB 35.82 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.52% 162.40 kB 163.25 kB +0.82% 35.76 kB 36.05 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.52% 164.69 kB 165.54 kB +0.82% 36.36 kB 36.66 kB
oss-stable-semver/react-server/cjs/react-server.development.js +0.30% 197.92 kB 198.53 kB +0.42% 46.59 kB 46.79 kB
oss-stable/react-server/cjs/react-server.development.js +0.30% 197.92 kB 198.53 kB +0.42% 46.59 kB 46.79 kB
oss-experimental/react-server/cjs/react-server.development.js +0.28% 213.55 kB 214.15 kB +0.39% 49.19 kB 49.38 kB
oss-stable-semver/react-server/cjs/react-server-flight.production.js +0.28% 41.69 kB 41.81 kB +0.40% 9.11 kB 9.14 kB
oss-stable/react-server/cjs/react-server-flight.production.js +0.28% 41.69 kB 41.81 kB +0.40% 9.11 kB 9.14 kB
oss-experimental/react-server/cjs/react-server-flight.production.js +0.21% 56.03 kB 56.15 kB +0.23% 11.14 kB 11.17 kB
test_utils/ReactAllWarnings.js Deleted 64.67 kB 0.00 kB Deleted 16.09 kB 0.00 kB

Generated by 🚫 dangerJS against 6c0f74a

@gnoff
Copy link
Collaborator Author

gnoff commented Jun 1, 2024

closing in favor of #29491

@gnoff gnoff closed this Jun 1, 2024
@gnoff gnoff deleted the render-microtask-pings-sync branch July 25, 2024 22:47
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.

3 participants