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

Rewrite ReactFiberScheduler for better integration with Scheduler package #15151

Merged
merged 10 commits into from
Apr 2, 2019

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Mar 19, 2019

Pushing this early so I won't lose my work if my computer combusts.

I'm not going to bother with splitting this into chunks until I get most/all of the tests passing. Then I'll work on getting it into a reviewable state. (It'll probably be hard to review regardless, though, given the nature of the PR.)

Intentional semantic differences

In the old implementation, in sync mode, retrying a previously suspended tree is synchronous inside the promise resolution callback. The new implementation schedules an async callback to perform the retry. If multiple promise resolutions occur before the async callback fires, they will be batched together.

Todo

  • Basic scheduling (no Suspense)
  • Error handling
  • Suspense
  • Replay errors in DEV with invokeGuardedCallback
  • Discrete input events
  • ReactDOM.createBatch
  • Profiler component
  • Interaction tracing
  • Batching of updates within the same event
  • 100% of tests passing
  • Fix Flow
  • Conditionally add FiberRoot fields that correspond to each Scheduler implementation so they don't increase bundle size
  • Create build that has feature flag enabled

@acdlite acdlite changed the title Rewrite ReactFiberScheduler for betting integration with Scheduler package Rewrite ReactFiberScheduler for better integration with Scheduler package Mar 19, 2019
@trueadm
Copy link
Contributor

trueadm commented Mar 19, 2019

Is it expected that React's size goes up by 1.4% gzip? :o

I thought with these changes it would have gone down. Maybe missing some DEV wrappers?

@acdlite
Copy link
Collaborator Author

acdlite commented Mar 19, 2019

@trueadm All the changes I've made in this PR are in a forked file that isn't enabled yet (except via yarn test-new-scheduler) so those numbers don't mean anything right now. I think sizebot is reporting an increase because I haven't rebased on top of master yet, which includes #15071, which decreased the size.

@acdlite
Copy link
Collaborator Author

acdlite commented Mar 19, 2019

Once this PR is ready, I would expect ReactDOM's size to go slightly down, or at least stay even. Scheduler might go up a bit if I end up lifting stuff into that package. React isomorphic package shouldn't be affected at all.

@acdlite acdlite force-pushed the root-scheduler branch 5 times, most recently from 50b7091 to 2d7a6ac Compare March 22, 2019 03:19
@acdlite acdlite force-pushed the root-scheduler branch 2 times, most recently from fc0d30e to f007ae7 Compare March 26, 2019 19:30
@sizebot
Copy link

sizebot commented Mar 26, 2019

ReactDOM: size: 🔺+0.2%, gzip: 🔺+0.3%

Details of bundled changes.

Comparing: aed0e1c...f1dc626

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +8.5% +8.3% 816.23 KB 885.6 KB 184.68 KB 200.06 KB UMD_DEV
react-dom.production.min.js 🔺+0.2% 🔺+0.3% 105.11 KB 105.29 KB 33.98 KB 34.1 KB UMD_PROD
react-dom.profiling.min.js +0.2% +0.3% 108.1 KB 108.3 KB 34.61 KB 34.71 KB UMD_PROFILING
react-dom.development.js +8.6% +8.4% 810.62 KB 880.22 KB 183.07 KB 198.5 KB NODE_DEV
react-dom.production.min.js 🔺+0.2% 🔺+0.3% 105.1 KB 105.27 KB 33.47 KB 33.56 KB NODE_PROD
react-dom.profiling.min.js +0.2% +0.2% 108.2 KB 108.39 KB 34.09 KB 34.14 KB NODE_PROFILING
ReactDOM-dev.js +8.5% +8.5% 835.54 KB 906.44 KB 184.71 KB 200.42 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.4% 🔺+0.2% 331.58 KB 332.91 KB 61.13 KB 61.26 KB FB_WWW_PROD
ReactDOM-profiling.js +0.4% +0.2% 338.12 KB 339.59 KB 62.52 KB 62.66 KB FB_WWW_PROFILING
react-dom-unstable-fire.development.js +8.5% +8.3% 816.55 KB 885.92 KB 184.81 KB 200.19 KB UMD_DEV
react-dom-unstable-fire.production.min.js 🔺+0.2% 🔺+0.4% 105.13 KB 105.3 KB 33.99 KB 34.11 KB UMD_PROD
react-dom-unstable-fire.profiling.min.js +0.2% +0.3% 108.11 KB 108.31 KB 34.62 KB 34.72 KB UMD_PROFILING
react-dom-unstable-fire.development.js +8.6% +8.4% 810.94 KB 880.54 KB 183.2 KB 198.63 KB NODE_DEV
react-dom-unstable-fire.production.min.js 🔺+0.2% 🔺+0.3% 105.11 KB 105.28 KB 33.47 KB 33.57 KB NODE_PROD
react-dom-unstable-fire.profiling.min.js +0.2% +0.2% 108.22 KB 108.4 KB 34.1 KB 34.15 KB NODE_PROFILING
ReactFire-dev.js +8.5% +8.5% 834.73 KB 905.63 KB 184.68 KB 200.39 KB FB_WWW_DEV
ReactFire-prod.js 🔺+0.4% 🔺+0.3% 320.24 KB 321.57 KB 58.77 KB 58.93 KB FB_WWW_PROD
ReactFire-profiling.js +0.5% +0.3% 326.73 KB 328.2 KB 60.16 KB 60.33 KB FB_WWW_PROFILING
react-dom-unstable-new-scheduler.development.js n/a n/a 0 B 879.4 KB 0 B 198.1 KB NODE_DEV
react-dom-unstable-new-scheduler.production.min.js n/a n/a 0 B 110.34 KB 0 B 35.21 KB NODE_PROD
ReactDOMNewScheduler-dev.js n/a n/a 0 B 905.34 KB 0 B 200.27 KB FB_WWW_DEV
ReactDOMNewScheduler-prod.js n/a n/a 0 B 314.83 KB 0 B 58.31 KB FB_WWW_PROD
ReactDOMNewScheduler-profiling.js n/a n/a 0 B 320.54 KB 0 B 59.38 KB FB_WWW_PROFILING
react-dom-test-utils.development.js 0.0% 0.0% 52 KB 52 KB 14.08 KB 14.08 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% -0.1% 10.42 KB 10.42 KB 3.84 KB 3.83 KB UMD_PROD
react-dom-test-utils.development.js 0.0% 0.0% 51.72 KB 51.72 KB 14.02 KB 14.02 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 10.2 KB 10.2 KB 3.76 KB 3.76 KB NODE_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.76 KB 60.76 KB 15.85 KB 15.85 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 🔺+0.1% 10.69 KB 10.69 KB 3.66 KB 3.67 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.43 KB 60.43 KB 15.72 KB 15.72 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 🔺+0.1% 10.42 KB 10.42 KB 3.56 KB 3.56 KB NODE_PROD
react-dom-server.browser.development.js 0.0% 0.0% 134.78 KB 134.78 KB 35.51 KB 35.51 KB UMD_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 19.05 KB 19.05 KB 7.18 KB 7.18 KB UMD_PROD
react-dom-server.browser.development.js 0.0% 0.0% 130.91 KB 130.91 KB 34.57 KB 34.57 KB NODE_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 18.98 KB 18.98 KB 7.17 KB 7.17 KB NODE_PROD
ReactDOMServer-dev.js 0.0% 0.0% 133.22 KB 133.22 KB 34.32 KB 34.32 KB FB_WWW_DEV
ReactDOMServer-prod.js 0.0% 0.0% 46.19 KB 46.19 KB 10.62 KB 10.63 KB FB_WWW_PROD
react-dom-server.node.development.js 0.0% 0.0% 132.86 KB 132.86 KB 35.11 KB 35.12 KB NODE_DEV
react-dom-server.node.production.min.js 0.0% 0.0% 19.84 KB 19.84 KB 7.48 KB 7.48 KB NODE_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.21 KB 1.21 KB 703 B 704 B UMD_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.49 KB 3.49 KB 1.41 KB 1.41 KB NODE_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.3% 1.05 KB 1.05 KB 634 B 636 B NODE_PROD
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 3.74 KB 3.74 KB 1.43 KB 1.43 KB NODE_DEV
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.2% 1.1 KB 1.1 KB 665 B 666 B NODE_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +11.6% +11.7% 568.93 KB 634.67 KB 122.77 KB 137.15 KB UMD_DEV
react-art.production.min.js 🔺+0.2% 🔺+0.1% 96.76 KB 97.01 KB 29.66 KB 29.7 KB UMD_PROD
react-art.development.js +13.2% +13.7% 499.84 KB 565.86 KB 105.42 KB 119.91 KB NODE_DEV
react-art.production.min.js 🔺+0.4% 🔺+0.4% 61.77 KB 62 KB 18.89 KB 18.96 KB NODE_PROD
ReactART-dev.js +13.2% +14.2% 509.8 KB 577 KB 104.69 KB 119.56 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.3% 🔺+0.4% 197.13 KB 197.62 KB 33.34 KB 33.46 KB FB_WWW_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +10.7% +11.3% 631.05 KB 698.53 KB 134.53 KB 149.67 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 🔺+0.1% 245.88 KB 246.13 KB 43.01 KB 43.06 KB RN_FB_PROD
ReactNativeRenderer-profiling.js -0.0% 0.0% 252.22 KB 252.15 KB 44.37 KB 44.37 KB RN_FB_PROFILING
ReactNativeRenderer-dev.js +10.7% +11.3% 630.97 KB 698.45 KB 134.5 KB 149.64 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 🔺+0.1% 245.89 KB 246.14 KB 43 KB 43.06 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js -0.0% 0.0% 252.24 KB 252.17 KB 44.37 KB 44.37 KB RN_OSS_PROFILING
ReactFabric-dev.js +10.9% +11.5% 619.9 KB 687.38 KB 131.88 KB 147.04 KB RN_FB_DEV
ReactFabric-prod.js 🔺+0.1% 🔺+0.2% 239.28 KB 239.45 KB 41.73 KB 41.8 KB RN_FB_PROD
ReactFabric-profiling.js 0.0% +0.2% 244.71 KB 244.75 KB 43.08 KB 43.14 KB RN_FB_PROFILING
ReactFabric-dev.js +10.9% +11.5% 619.81 KB 687.29 KB 131.83 KB 146.99 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.1% 🔺+0.2% 239.29 KB 239.46 KB 41.73 KB 41.79 KB RN_OSS_PROD
ReactFabric-profiling.js 0.0% +0.2% 244.72 KB 244.76 KB 43.07 KB 43.14 KB RN_OSS_PROFILING

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +13.0% +13.6% 513.51 KB 580.45 KB 108.13 KB 122.87 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.4% 🔺+0.5% 63.02 KB 63.25 KB 19.25 KB 19.34 KB UMD_PROD
react-test-renderer.development.js +13.2% +13.7% 509.03 KB 576.07 KB 106.98 KB 121.68 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.4% 🔺+0.4% 62.72 KB 62.95 KB 19.07 KB 19.16 KB NODE_PROD
ReactTestRenderer-dev.js +13.1% +14.2% 520.55 KB 588.81 KB 106.83 KB 121.99 KB FB_WWW_DEV
react-test-renderer-shallow.development.js 0.0% 0.0% 38.98 KB 38.98 KB 9.81 KB 9.81 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.42 KB 11.42 KB 3.5 KB 3.5 KB UMD_PROD
react-test-renderer-shallow.development.js 0.0% 0.0% 33.2 KB 33.2 KB 8.41 KB 8.41 KB NODE_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.61 KB 11.61 KB 3.63 KB 3.63 KB NODE_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +13.9% +14.7% 500.11 KB 569.52 KB 104.24 KB 119.52 KB NODE_DEV
react-reconciler.production.min.js -0.0% -0.0% 62.99 KB 62.96 KB 18.73 KB 18.73 KB NODE_PROD
react-reconciler-persistent.development.js +13.9% +14.8% 498 KB 567.4 KB 103.37 KB 118.66 KB NODE_DEV
react-reconciler-persistent.production.min.js -0.0% -0.0% 63 KB 62.97 KB 18.74 KB 18.73 KB NODE_PROD
react-reconciler-reflection.development.js 0.0% 0.0% 15.79 KB 15.79 KB 4.91 KB 4.91 KB NODE_DEV
react-reconciler-reflection.production.min.js 0.0% 🔺+0.2% 2.37 KB 2.37 KB 1.06 KB 1.07 KB NODE_PROD

Generated by 🚫 dangerJS

@acdlite acdlite force-pushed the root-scheduler branch 5 times, most recently from d739dca to 2f60c47 Compare March 29, 2019 22:17
@acdlite acdlite marked this pull request as ready for review March 29, 2019 22:31
@acdlite acdlite force-pushed the root-scheduler branch 4 times, most recently from 396abed to 3b89f99 Compare April 1, 2019 21:00
Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

The bundle size is up. What's that about?

packages/react-reconciler/src/ReactDebugFiberPerf.js Outdated Show resolved Hide resolved
scripts/rollup/forks.js Outdated Show resolved Hide resolved
@@ -1352,6 +1354,9 @@ describe('Profiler', () => {
},
);
}).toThrow('Expected error onWorkScheduled');
if (enableNewScheduler) {
expect(Scheduler).toFlushAndYield(['Component:fail']);
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's happening here?

packages/scheduler/src/Scheduler.js Outdated Show resolved Hide resolved
@acdlite
Copy link
Collaborator Author

acdlite commented Apr 1, 2019

Re: bundle size, I think it might be the inferPriorityFromExpirationTime function. I'll look into it.

Adds a new implementation of ReactFiberScheduler behind a feature flag.
We will maintain both implementations in parallel until the new one
is proven stable enough to replace the old one.

The main difference between the implementations is that the new one is
integrated with the Scheduler package's priority levels.
Some fields only used by the old scheduler, and some by the new.
If synchronous updates are scheduled by a passive effect, that work
should be flushed synchronously, even if flushPassiveEffects is
called inside batchedUpdates.
React doesn't need this anyway because it never schedules callbacks if
it's already rendering.
Turns out this isn't neccessary.
Should initialize to nothing, then assign the exports conditionally,
instead of initializing to the old exports and then reassigning to the
new ones.
Instead of wrapping in enableNewScheduler flag.
@acdlite acdlite merged commit 4d5cb64 into facebook:master Apr 2, 2019
@gaearon gaearon mentioned this pull request Apr 20, 2019
63 tasks
NMinhNguyen referenced this pull request in enzymejs/react-shallow-renderer Jan 29, 2020
…kage (#15151)

* Rewrite ReactFiberScheduler

Adds a new implementation of ReactFiberScheduler behind a feature flag.
We will maintain both implementations in parallel until the new one
is proven stable enough to replace the old one.

The main difference between the implementations is that the new one is
integrated with the Scheduler package's priority levels.

* Conditionally add fields to FiberRoot

Some fields only used by the old scheduler, and some by the new.

* Add separate build that enables new scheduler

* Re-enable skipped test

If synchronous updates are scheduled by a passive effect, that work
should be flushed synchronously, even if flushPassiveEffects is
called inside batchedUpdates.

* Passive effects have same priority as render

* Revert ability to cancel the current callback

React doesn't need this anyway because it never schedules callbacks if
it's already rendering.

* Revert change to FiberDebugPerf

Turns out this isn't neccessary.

* Fix ReactFiberScheduler dead code elimination

Should initialize to nothing, then assign the exports conditionally,
instead of initializing to the old exports and then reassigning to the
new ones.

* Don't yield before commit during sync error retry

* Call Scheduler.flushAll unconditionally in tests

Instead of wrapping in enableNewScheduler flag.
sebmarkbage added a commit to sebmarkbage/react that referenced this pull request Dec 10, 2020
We replay errors so you can break on paused exceptions. This is done in
the second pass so that the first pass can ignore suspense.

Originally this threw the original error. For suppression purposes
we copied the flag onto the original error.

https://github.com/facebook/react/blob/f1dc626b29b8bf0f14c75a8525e8650b7ea94a47/packages/react-reconciler/src/ReactFiberScheduler.old.js#L367-L369

During this refactor it changed to just throw the retried error:

facebook#15151

We're not sure exactly why but it was likely just an optimization or
clean up.

So we can go back to throwing the original error. That helps in the case
where a memoized function is naively not rethrowing each time such as
in Node's module system.
sebmarkbage added a commit to sebmarkbage/react that referenced this pull request Dec 10, 2020
We replay errors so you can break on paused exceptions. This is done in
the second pass so that the first pass can ignore suspense.

Originally this threw the original error. For suppression purposes
we copied the flag onto the original error.

https://github.com/facebook/react/blob/f1dc626b29b8bf0f14c75a8525e8650b7ea94a47/packages/react-reconciler/src/ReactFiberScheduler.old.js#L367-L369

During this refactor it changed to just throw the retried error:

facebook#15151

We're not sure exactly why but it was likely just an optimization or
clean up.

So we can go back to throwing the original error. That helps in the case
where a memoized function is naively not rethrowing each time such as
in Node's module system.

Unfortunately this doesn't fix the problem fully.
Because invokeGuardedCallback captures the error and logs it to the browser.
So you still end up seeing the wrong message in the logs.

This just fixes so that the error boundary sees the first one.
sebmarkbage added a commit that referenced this pull request Dec 10, 2020
We replay errors so you can break on paused exceptions. This is done in
the second pass so that the first pass can ignore suspense.

Originally this threw the original error. For suppression purposes
we copied the flag onto the original error.

https://github.com/facebook/react/blob/f1dc626b29b8bf0f14c75a8525e8650b7ea94a47/packages/react-reconciler/src/ReactFiberScheduler.old.js#L367-L369

During this refactor it changed to just throw the retried error:

#15151

We're not sure exactly why but it was likely just an optimization or
clean up.

So we can go back to throwing the original error. That helps in the case
where a memoized function is naively not rethrowing each time such as
in Node's module system.

Unfortunately this doesn't fix the problem fully.
Because invokeGuardedCallback captures the error and logs it to the browser.
So you still end up seeing the wrong message in the logs.

This just fixes so that the error boundary sees the first one.
koto pushed a commit to koto/react that referenced this pull request Jun 15, 2021
We replay errors so you can break on paused exceptions. This is done in
the second pass so that the first pass can ignore suspense.

Originally this threw the original error. For suppression purposes
we copied the flag onto the original error.

https://github.com/facebook/react/blob/f1dc626b29b8bf0f14c75a8525e8650b7ea94a47/packages/react-reconciler/src/ReactFiberScheduler.old.js#L367-L369

During this refactor it changed to just throw the retried error:

facebook#15151

We're not sure exactly why but it was likely just an optimization or
clean up.

So we can go back to throwing the original error. That helps in the case
where a memoized function is naively not rethrowing each time such as
in Node's module system.

Unfortunately this doesn't fix the problem fully.
Because invokeGuardedCallback captures the error and logs it to the browser.
So you still end up seeing the wrong message in the logs.

This just fixes so that the error boundary sees the first one.
@facebook-github-bot facebook-github-bot added the React Core Team Opened by a member of the React Core Team label Apr 15, 2024
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