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

Don't cache subelements #468

Merged
merged 3 commits into from
Sep 21, 2023
Merged

Don't cache subelements #468

merged 3 commits into from
Sep 21, 2023

Conversation

watt
Copy link
Collaborator

@watt watt commented Sep 20, 2023

Summary

In LayoutStorage we cache subelements, under the assumption that they will remain stable during a layout pass. This PR removes the caching, because it was a faulty assumption.

Details

In LayoutStorage we currently assume the array of LayoutSubelements for subelements will be stable during a layout pass, and cache it on the LayoutTreeNode. This was assumed safe because LayoutStorage-backed themselves elements cannot vary during a layout pass, and LazyStorage, which can, does not cache its subelement at all.

Turns out there is a case where this assumption is violated, if a LazyStorage produces a subtree that varies somewhere in a descendant node. For example, a GeometryReader that contains a stack, and varies the number of children in the stack based on space available.

Performance

This PR is broken into 2 commits:

  • First, a fix that is guarded behind a LayoutMode option. This option was used to performance test this change against the current behavior as a baseline.
  • The second commit removes the option and adopts the fix unconditionally.

I was expecting to incur a hit from removing this caching but benchmarking showed it to be completely negligible, and attempts to more cleverly cache actually performed worse. I'll put up a Market PR that shows this benchmark and a regression test.

Testing

There's a new GeometryReader test to validate this case, and regression test will be on the Market side.

See UI-4599.

@watt watt force-pushed the watt/variable-subelements-fix branch from d941d5c to f2f03f9 Compare September 20, 2023 18:38
@watt watt marked this pull request as ready for review September 20, 2023 18:44
@watt watt requested a review from a team as a code owner September 20, 2023 18:44
Copy link
Collaborator

@kyleve kyleve left a comment

Choose a reason for hiding this comment

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

Thanks for getting this through!

Comment on lines +135 to +141
return LayoutSubelement(
identifier: identifier,
content: child.content,
environment: environment,
node: node.subnode(key: identifier),
traits: child.traits
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Details of the alternatives I attempted:

  • Caching each LayoutSubelement by identifier. This didn't work because child.content may vary and need to be re-evaluated.
  • Making LayoutSubelement capture child.content as a closure and lazily evaluate it once the first time it is needed. Had no impact on performance.

@watt watt merged commit fc19f17 into main Sep 21, 2023
5 checks passed
@watt watt deleted the watt/variable-subelements-fix branch September 21, 2023 02:03
This was referenced Sep 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants