[Optimization] Reduce unnecessary Component rebuilds#1754
Merged
hecrj merged 1 commit intoiced-rs:masterfrom Mar 23, 2023
Merged
[Optimization] Reduce unnecessary Component rebuilds#1754hecrj merged 1 commit intoiced-rs:masterfrom
Component rebuilds#1754hecrj merged 1 commit intoiced-rs:masterfrom
Conversation
76c569a to
a3f6b78
Compare
hecrj
approved these changes
Mar 23, 2023
Member
hecrj
left a comment
There was a problem hiding this comment.
Clever! The lazy crate is getting quite insane. Hopefully we can identify a pattern at some point.
Also, I would generally recommend to avoid nesting Component. A custom widget may work better for containers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The current implementation of
Componentresults in many unnecessary rebuilds when components are nested inside the view of other components. This can be observed in the following example, with several layers of nested components (code):unoptimized.mov
This PR optimizes
Componentto avoid unnecessary rebuilds, after which running the same example results in:optimized.mov
The cause of excessive rebuilding in the existing implementation is that the component's underlying element is rebuilt eagerly after any potential state mutation. If the component returns a message from
update, processing that message at a parent component (or the root application level), will in turn cause another rebuild of the component just built. As a result, with increasing layers of components, the runtime of processing an event which propagates to the root of the application increases in a non-linear fashion.By deferring rebuild until any widget method is invoked where the latest element is actually required, we can perform this same process in linear time.
If the rebuild is to be deferred until absolutely necessary, invocation of any widget method may require rebuilding of the component's element, and in turn requires diffing of that element's widget sub-tree. This means that mutable access to the element's widget sub-tree is required during every widget method. To achieve this, the widget tree for the component's contained element is moved inside of the component-widget's state and put inside a
RefCell. Sincewidth,heightandlayoutdo not have even immutable access to the widget tree, but may still be invoked and require rebuilding of the element, anRcis used to store a reference to the sub-tree on the component-widget instance itself, and populated during diffing (similar to the approach used in theLazywidget). This allows mutable access to the element's widget tree from any widget method without altering theWidgetinterface.For
overlay, the contained element's widget sub-tree is moved onto the overlay element, and restored during the overlay's drop (again, similar to how overlay works in theLazywidget).This implementation has been tested in a relatively large real-world application having many layers of components both inside & outside overlays. No issues or discrepancies from the current implementation of
Componenthave yet been identified.