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

Hooks Refactor Update Queue by Cloning Rebased Updates #17483

Closed
wants to merge 2 commits into from

Conversation

sebmarkbage
Copy link
Collaborator

Builds on top of #17480.

Alternative to #17430.

This model splits the update queue into two (cyclic) linked lists. There is one each for current/workInProgress pair for rebase purposes. There is also one shared one.

When we process a queue we merge the shared onto the "current" one, and clone it onto the work in progress.

The cloned one doesn't include the beginning of the queue that is fully processed.

The cloned nodes that were processed get Sync priority so that they don't get dropped during future renders.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 28, 2019

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 89ca3cf:

Sandbox Source
determined-bush-82zu4 Configuration

@sizebot
Copy link

sizebot commented Nov 28, 2019

Details of bundled changes.

Comparing: 3c1efa0...89ca3cf

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.production.min.js 🔺+0.5% 🔺+0.3% 72.57 KB 72.91 KB 21.32 KB 21.39 KB NODE_PROD
react-reconciler-reflection.production.min.js 0.0% 🔺+0.1% 2.85 KB 2.85 KB 1.23 KB 1.24 KB NODE_PROD
react-reconciler-persistent.development.js +0.2% +0.2% 603.38 KB 604.34 KB 127.03 KB 127.26 KB NODE_DEV
react-reconciler-persistent.production.min.js 🔺+0.5% 🔺+0.3% 72.58 KB 72.92 KB 21.32 KB 21.4 KB NODE_PROD
react-reconciler.development.js +0.2% +0.2% 605.91 KB 606.87 KB 128.14 KB 128.37 KB NODE_DEV
react-reconciler-reflection.development.js 0.0% 0.0% 19.08 KB 19.08 KB 6.23 KB 6.23 KB NODE_DEV

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.46 KB 10.46 KB 3.56 KB 3.57 KB NODE_PROD
react-dom-server.browser.development.js 0.0% 0.0% 136.58 KB 136.58 KB 35.94 KB 35.94 KB NODE_DEV
react-dom.development.js +0.1% +0.1% 955.64 KB 956.61 KB 216.03 KB 216.27 KB UMD_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 19.85 KB 19.85 KB 7.38 KB 7.38 KB NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.87 KB 3.87 KB 1.54 KB 1.54 KB UMD_DEV
react-dom.production.min.js 🔺+0.3% 🔺+0.2% 116.39 KB 116.73 KB 37.45 KB 37.52 KB UMD_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.2 KB 1.2 KB 701 B 702 B UMD_PROD
react-dom.profiling.min.js +0.3% +0.2% 119.96 KB 120.29 KB 38.56 KB 38.63 KB UMD_PROFILING
react-dom.development.js +0.1% +0.1% 949.71 KB 950.67 KB 214.46 KB 214.69 KB NODE_DEV
react-dom.production.min.js 🔺+0.3% 🔺+0.2% 116.5 KB 116.84 KB 36.86 KB 36.92 KB NODE_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.2% 1.04 KB 1.04 KB 632 B 633 B NODE_PROD
react-dom.profiling.min.js +0.3% +0.2% 120.19 KB 120.53 KB 37.84 KB 37.93 KB NODE_PROFILING
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.72 KB 10.72 KB 3.66 KB 3.67 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 59.76 KB 59.76 KB 15.64 KB 15.64 KB NODE_DEV
react-dom-server.node.development.js 0.0% 0.0% 137.69 KB 137.69 KB 36.16 KB 36.16 KB NODE_DEV
react-dom-test-utils.development.js 0.0% 0.0% 56.17 KB 56.17 KB 15.54 KB 15.54 KB UMD_DEV
react-dom-server.node.production.min.js 0.0% 0.0% 20.26 KB 20.26 KB 7.53 KB 7.53 KB NODE_PROD
react-dom-test-utils.production.min.js 0.0% 🔺+0.1% 11.17 KB 11.17 KB 4.14 KB 4.14 KB UMD_PROD
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 4.4 KB 4.4 KB 1.64 KB 1.64 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% 🔺+0.1% 10.94 KB 10.94 KB 4.08 KB 4.08 KB NODE_PROD
react-dom-server.browser.development.js 0.0% 0.0% 140.64 KB 140.64 KB 36.93 KB 36.94 KB UMD_DEV

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.1% +0.2% 674.22 KB 675.18 KB 146.34 KB 146.57 KB UMD_DEV
react-art.production.min.js 🔺+0.3% 🔺+0.3% 104.79 KB 105.13 KB 31.83 KB 31.93 KB UMD_PROD
react-art.development.js +0.2% +0.2% 604.86 KB 605.82 KB 128.94 KB 129.17 KB NODE_DEV
react-art.production.min.js 🔺+0.5% 🔺+0.3% 69.8 KB 70.14 KB 21.01 KB 21.07 KB NODE_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.2% +0.2% 619.14 KB 620.1 KB 132.01 KB 132.24 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.5% 🔺+0.2% 71.82 KB 72.15 KB 21.93 KB 21.99 KB UMD_PROD
react-test-renderer.development.js +0.2% +0.2% 614.41 KB 615.37 KB 130.83 KB 131.06 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.5% 🔺+0.3% 71.52 KB 71.86 KB 21.57 KB 21.63 KB NODE_PROD
react-test-renderer-shallow.development.js 0.0% 0.0% 39.13 KB 39.13 KB 10 KB 10 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.58 KB 11.58 KB 3.57 KB 3.57 KB UMD_PROD
react-test-renderer-shallow.development.js 0.0% 0.0% 33.09 KB 33.09 KB 8.52 KB 8.53 KB NODE_DEV
react-test-renderer-shallow.production.min.js 0.0% 🔺+0.1% 11.72 KB 11.72 KB 3.68 KB 3.68 KB NODE_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.1% +0.1% 750.55 KB 751.38 KB 158.96 KB 159.14 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.3% 🔺+0.2% 277.29 KB 278.13 KB 47.6 KB 47.7 KB RN_FB_PROD
ReactNativeRenderer-profiling.js +0.3% +0.2% 286.22 KB 287.06 KB 49.32 KB 49.42 KB RN_FB_PROFILING
ReactFabric-dev.js +0.1% +0.1% 756 KB 756.82 KB 159.8 KB 159.97 KB RN_FB_DEV
ReactFabric-prod.js 🔺+0.3% 🔺+0.2% 268.95 KB 269.79 KB 46.21 KB 46.31 KB RN_FB_PROD
ReactFabric-profiling.js +0.3% +0.2% 279.05 KB 279.89 KB 48.05 KB 48.15 KB RN_FB_PROFILING
ReactNativeRenderer-dev.js +0.1% +0.1% 750.38 KB 751.2 KB 158.88 KB 159.05 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 🔺+0.3% 🔺+0.2% 276.9 KB 277.74 KB 47.53 KB 47.63 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.3% +0.2% 285.83 KB 286.67 KB 49.25 KB 49.35 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 755.82 KB 756.64 KB 159.72 KB 159.89 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.3% 🔺+0.2% 268.6 KB 269.44 KB 46.13 KB 46.23 KB RN_OSS_PROD
ReactFabric-profiling.js +0.3% +0.2% 278.71 KB 279.54 KB 47.98 KB 48.08 KB RN_OSS_PROFILING

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

Size changes (stable)

Generated by 🚫 dangerJS against 89ca3cf

@sizebot
Copy link

sizebot commented Nov 28, 2019

Details of bundled changes.

Comparing: 3c1efa0...89ca3cf

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js +0.3% +0.2% 123.69 KB 124.02 KB 38.81 KB 38.88 KB NODE_PROFILING
react-dom-server.browser.development.js 0.0% 0.0% 140.67 KB 140.67 KB 36.94 KB 36.94 KB UMD_DEV
react-dom-test-utils.development.js 0.0% 0.0% 56.18 KB 56.18 KB 15.54 KB 15.54 KB UMD_DEV
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.88 KB 3.88 KB 1.55 KB 1.55 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% 🔺+0.1% 11.18 KB 11.18 KB 4.15 KB 4.15 KB UMD_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.3% 1.21 KB 1.21 KB 708 B 710 B UMD_PROD
ReactDOMServer-dev.js 0.0% 0.0% 140.21 KB 140.21 KB 35.48 KB 35.48 KB FB_WWW_DEV
react-dom-test-utils.development.js 0.0% 0.0% 54.45 KB 54.45 KB 15.21 KB 15.21 KB NODE_DEV
ReactDOMServer-prod.js 0.0% 0.0% 48.91 KB 48.91 KB 11.18 KB 11.18 KB FB_WWW_PROD
react-dom-test-utils.production.min.js 0.0% 🔺+0.1% 10.95 KB 10.95 KB 4.09 KB 4.09 KB NODE_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.2% 1.05 KB 1.05 KB 640 B 641 B NODE_PROD
react-dom.development.js +0.1% +0.1% 955.66 KB 956.63 KB 216.06 KB 216.29 KB UMD_DEV
react-dom.production.min.js 🔺+0.3% 🔺+0.1% 119.74 KB 120.08 KB 38.46 KB 38.5 KB UMD_PROD
react-dom.profiling.min.js +0.3% +0.2% 123.42 KB 123.76 KB 39.56 KB 39.64 KB UMD_PROFILING
react-dom.development.js +0.1% +0.1% 949.73 KB 950.7 KB 214.48 KB 214.71 KB NODE_DEV
react-dom-server.node.development.js 0.0% 0.0% 137.71 KB 137.71 KB 36.16 KB 36.17 KB NODE_DEV
react-dom.production.min.js 🔺+0.3% 🔺+0.2% 119.88 KB 120.22 KB 37.79 KB 37.87 KB NODE_PROD
react-dom-server.browser.development.js 0.0% 0.0% 136.6 KB 136.6 KB 35.94 KB 35.94 KB NODE_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 20.31 KB 20.31 KB 7.46 KB 7.46 KB NODE_PROD
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.73 KB 10.73 KB 3.67 KB 3.67 KB UMD_PROD
ReactDOM-dev.js +0.1% +0.1% 978.24 KB 979.06 KB 217.02 KB 217.19 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.2% 🔺+0.1% 402.25 KB 403.08 KB 73.07 KB 73.15 KB FB_WWW_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 59.77 KB 59.77 KB 15.65 KB 15.65 KB NODE_DEV
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 4.42 KB 4.42 KB 1.65 KB 1.65 KB NODE_DEV
ReactDOM-profiling.js +0.2% +0.1% 404.04 KB 404.88 KB 74.01 KB 74.09 KB FB_WWW_PROFILING
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.1% 1.21 KB 1.21 KB 696 B 697 B NODE_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactFabric-prod.js 🔺+0.3% 🔺+0.2% 268.96 KB 269.8 KB 46.22 KB 46.32 KB RN_FB_PROD
ReactNativeRenderer-dev.js +0.1% +0.1% 750.39 KB 751.21 KB 158.89 KB 159.06 KB RN_OSS_DEV
ReactFabric-profiling.js +0.3% +0.2% 279.07 KB 279.9 KB 48.06 KB 48.16 KB RN_FB_PROFILING
ReactNativeRenderer-prod.js 🔺+0.3% 🔺+0.2% 277.3 KB 278.14 KB 47.61 KB 47.71 KB RN_FB_PROD
ReactNativeRenderer-profiling.js +0.3% +0.2% 286.23 KB 287.07 KB 49.33 KB 49.43 KB RN_FB_PROFILING
ReactFabric-dev.js +0.1% +0.1% 755.83 KB 756.65 KB 159.73 KB 159.9 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.3% 🔺+0.2% 268.61 KB 269.45 KB 46.14 KB 46.24 KB RN_OSS_PROD
ReactFabric-profiling.js +0.3% +0.2% 278.72 KB 279.56 KB 47.99 KB 48.08 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 756.01 KB 756.83 KB 159.81 KB 159.98 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.3% 🔺+0.2% 276.91 KB 277.75 KB 47.54 KB 47.63 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.3% +0.2% 285.85 KB 286.68 KB 49.26 KB 49.36 KB RN_OSS_PROFILING
ReactNativeRenderer-dev.js +0.1% +0.1% 750.57 KB 751.39 KB 158.97 KB 159.15 KB RN_FB_DEV

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.2% +0.2% 619.16 KB 620.13 KB 132.02 KB 132.26 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.5% 🔺+0.2% 71.85 KB 72.18 KB 21.95 KB 22 KB UMD_PROD
ReactTestRenderer-dev.js +0.1% +0.1% 629.94 KB 630.76 KB 131.2 KB 131.37 KB FB_WWW_DEV
react-test-renderer-shallow.development.js 0.0% 0.0% 39.15 KB 39.15 KB 10.01 KB 10.01 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.6 KB 11.6 KB 3.58 KB 3.58 KB UMD_PROD
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.73 KB 11.73 KB 3.69 KB 3.69 KB NODE_PROD
react-test-renderer.development.js +0.2% +0.2% 614.43 KB 615.4 KB 130.84 KB 131.07 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.5% 🔺+0.3% 71.54 KB 71.88 KB 21.59 KB 21.64 KB NODE_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactART-dev.js +0.1% +0.1% 618.27 KB 619.09 KB 128.63 KB 128.8 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.4% 🔺+0.2% 235.6 KB 236.44 KB 39.88 KB 39.98 KB FB_WWW_PROD
react-art.development.js +0.1% +0.2% 674.24 KB 675.2 KB 146.34 KB 146.57 KB UMD_DEV
react-art.production.min.js 🔺+0.3% 🔺+0.2% 106.81 KB 107.15 KB 32.43 KB 32.49 KB UMD_PROD
react-art.development.js +0.2% +0.2% 604.88 KB 605.85 KB 128.95 KB 129.17 KB NODE_DEV
react-art.production.min.js 🔺+0.5% 🔺+0.3% 71.78 KB 72.11 KB 21.49 KB 21.56 KB NODE_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler-persistent.development.js +0.2% +0.2% 603.39 KB 604.35 KB 127.04 KB 127.27 KB NODE_DEV
react-reconciler-persistent.production.min.js 🔺+0.5% 🔺+0.3% 72.59 KB 72.93 KB 21.33 KB 21.4 KB NODE_PROD
react-reconciler-reflection.production.min.js 0.0% 🔺+0.1% 2.86 KB 2.86 KB 1.24 KB 1.24 KB NODE_PROD
react-reconciler.development.js +0.2% +0.2% 605.92 KB 606.88 KB 128.14 KB 128.37 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.5% 🔺+0.3% 74.81 KB 75.15 KB 21.9 KB 21.97 KB NODE_PROD

Size changes (experimental)

Generated by 🚫 dangerJS against 89ca3cf

Copy link
Collaborator

@acdlite acdlite left a comment

Choose a reason for hiding this comment

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

Neat! But I don't think we should land without fixing classes too. I can pick up that part next week when I'm back from PTO, if you want.

} else {
first = last !== null ? last.next : null;
current.baseQueue = baseQueue = pendingQueue;
queue.pending = null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I love this trick

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I believe we could use this same trick for expirationTimes. By storing it temporarily on a shared stateful object and then transferring it to “current”. That way we don’t need the alternate model when we backtrack and can just backtrack along on a shared object path.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah I used a similar trick for the eager bailout optimization. Where I reset current.expirationTime to NoWork after a bailout. Also in my useTransition PR to clear a pending transition. Such a nice strategy.

@sebmarkbage
Copy link
Collaborator Author

We might want to add an optimization to avoid cloning the queue when something else renders at higher pri. In that case it’s unnecessary to clone it.

Adds a failing test case where an update that was committed is
later skipped over during a rebase. This should never happen.
acdlite added a commit that referenced this pull request Dec 9, 2019
Fixes a bug related to rebasing updates. Once an update has committed,
it should never un-commit, even if interrupted by a higher priority
update. The fix includes a refactor of how update queues work.

This commit is a combination of two PRs:

- #17483 by @sebmarkbage refactors the hook update queue
- #17510 by @acdlite refactors the class and root update queue

Landing one without the other would cause state updates to sometimes be
inconsistent across components, so I've combined them into a single
commit in case they need to be reverted.

Co-authored-by: Sebastian Markbåge <sema@fb.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>
@acdlite
Copy link
Collaborator

acdlite commented Dec 9, 2019

I squashed this with the class refactor and landed as b617db3 so it can be atomically reverted.

@acdlite acdlite closed this Dec 9, 2019
acdlite added a commit to acdlite/react that referenced this pull request Dec 9, 2019
Fixes a bug related to rebasing updates. Once an update has committed,
it should never un-commit, even if interrupted by a higher priority
update. The fix includes a refactor of how update queues work.

This commit is a combination of two PRs:

- facebook#17483 by @sebmarkbage refactors the hook update queue
- facebook#17510 by @acdlite refactors the class and root update queue

Landing one without the other would cause state updates to sometimes be
inconsistent across components, so I've combined them into a single
commit in case they need to be reverted.

Co-authored-by: Sebastian Markbåge <sema@fb.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>
acdlite added a commit that referenced this pull request Dec 11, 2019
* Refactor Update Queues to Fix Rebasing Bug

Fixes a bug related to rebasing updates. Once an update has committed,
it should never un-commit, even if interrupted by a higher priority
update. The fix includes a refactor of how update queues work.

This commit is a combination of two PRs:

- #17483 by @sebmarkbage refactors the hook update queue
- #17510 by @acdlite refactors the class and root update queue

Landing one without the other would cause state updates to sometimes be
inconsistent across components, so I've combined them into a single
commit in case they need to be reverted.

Co-authored-by: Sebastian Markbåge <sema@fb.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>

* Initialize update queue object on mount

Instead of lazily initializing update queue objects on the first update,
class and host root queues are created on mount. This simplifies the
logic for appending new updates and matches what we do for hooks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants