-
Notifications
You must be signed in to change notification settings - Fork 45.7k
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
SuspenseList Optimizations #16005
SuspenseList Optimizations #16005
Conversation
ReactDOM: size: 0.0%, gzip: 🔺+0.1% Details of bundled changes.Comparing: fbbbea1...ea6d36c react-dom
react-art
react-test-renderer
react-native-renderer
react-reconciler
Generated by 🚫 dangerJS |
// something in the previous committed pass suspended. Otherwise, | ||
// there's no chance so we can skip the expensive call to | ||
// hasSuspendedChildrenAndNewContent. | ||
let cannotBeSuspended = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like something we could put on the effectTag
or a similar bitfield that gets bubbled up during complete/unwind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I wanted a tag on each child so that I can use it to efficiently determine the tail in beginWork.
We now are able to bail out of reconciliation and splitting out the tail during deep updates that hasn't changed the child props. This only works while the list wasn't suspended before. I also moved the second render of the "head" to the complete phase. This cleans it up a bit for the tail collapsing PR. For this second pass I also use a new technique of resetting the child Fibers for the second pass. This is effectively a fast path to avoid reconciling the children against props again.
The effectTag now tracks whether the previous commit was suspended. This frees up SuspenseListState to be render-phase only state. We use null to mean the default "independent" mode.
…spended This optimized the deep update case or initial render without anything suspending. We have some information available to us that tell us if nothing has suspended in the past and nothing has suspended this render pass. This also fixes a bug where we didn't tag the previous render as having suspended boundaries if we didn't need to force a rerender.
oops
46a3ede
to
ea6d36c
Compare
* Add a bunch of optimizations to SuspenseList We now are able to bail out of reconciliation and splitting out the tail during deep updates that hasn't changed the child props. This only works while the list wasn't suspended before. I also moved the second render of the "head" to the complete phase. This cleans it up a bit for the tail collapsing PR. For this second pass I also use a new technique of resetting the child Fibers for the second pass. This is effectively a fast path to avoid reconciling the children against props again. * Move to didSuspend from SuspenseListState to the effectTag The effectTag now tracks whether the previous commit was suspended. This frees up SuspenseListState to be render-phase only state. We use null to mean the default "independent" mode. * Rename to SuspenseListState to SuspenseListRenderState * Reuse SuspenseListRenderState across render passes * Add optimization to bail out of scanning children if they can't be suspended This optimized the deep update case or initial render without anything suspending. We have some information available to us that tell us if nothing has suspended in the past and nothing has suspended this render pass. This also fixes a bug where we didn't tag the previous render as having suspended boundaries if we didn't need to force a rerender. * rm printChildren oops
This includes a bunch of refactoring and optimizations to SuspenseList. Individual commits help the review.
The biggest optimization focus on the common case of deep updates inside a fully completed tree.
In the case where nothing in the list was suspended and the children didn't change, we now avoid scanning through the list in the begin phase since we don't need to find a tail.
Additionally, if nothing new suspended in this whole render pass, we can also skip the scan in the complete phase.