Made Directionality forego dependency tracking for better performance.#102336
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
|
The widget test is legitimately broken. I'm going to take this PR out of review until I fixed it. |
a0b5c0c to
7fb7ce9
Compare
|
Okay, I fixed the tests. I previously wasn't recursing into the children elements and I had to make updates get filtered based on the bookkeeping we are keeping lower in the tree to match existing behavior. I had to make one tiny addition to the Element api. |
|
Some questions I have about this approach - how well does this scale in the odd case where users override directionality? What is the cost of updating the widget tree if the directionality does change? Finally, how does the performance improvement scale to less constrained devices? I'm assuming the number comes from a wembly? |
What does this mean? Did it make the benchmark worse? What is the expected performance benefit of this change? |
There was a problem hiding this comment.
I thought about it but I don't know what our policy is there. You probably know better. We can't guarantee that the assert would always get hit in debug build and not release build. If Directionality ends up being the only user of it it might not be a big deal. I was just erring on the side of caution.
There was a problem hiding this comment.
I would just go with the assert here for now.
There was a problem hiding this comment.
(oops, fixed it, good now)
There was a problem hiding this comment.
nit: a future reader will probably appreciate a little more documentation on how this is different from the regular InheritedElement.
There was a problem hiding this comment.
This override seems unnecessary?
There was a problem hiding this comment.
I did this in order to convert a @protected method to a public one. I don't know if there is an easier way.
There was a problem hiding this comment.
Oh, right. Makes sense then :)
There was a problem hiding this comment.
For my own understanding: Is the optimization here that we omit the bookkeeping that originally happened in this method? (Adding the dependent to a map?)
There was a problem hiding this comment.
Yep, that's correct. You can see that in the profile I linked in the internal bug.
There was a problem hiding this comment.
Maybe leave that as a comment here for future readers, who want to understand why we did this.
Nope, an increase in performance, a decrease in time. I wouldn't recommend a change that doesn't help haha.
In the |
Does this change translate to a 20ms faster startup time for customer:money then? |
|
Ahh Iphone SE, not bad |
|
Another follow up question: can we identify other inherited widgets that frequently don't change? |
We are switching our algorithm from:
Insertions are happening when we are building the widget tree, lookups happen when the widget decides its data has changed and needs to notify its dependencies. So, the performance will be somewhere between where it was before the change and a hot reload. It won't be as costly as a hot reload because we are still filtering updates to widgets that actually depend on the widget. I think in practice
My local testing was done on a modern iPhone and the supporting evidence for the change was the profiles of low end android devices. I suspect this to be a win across the board. |
I think there is an opportunity to. The other widgets I identified as candidates are [MediaQuery] and [Theme]. I know less about those and how much they change. Also, making them |
I didn't run the test for customer:money since it is a bit involved. I felt I had enough evidence in hand to know it would be beneficial and I'd get the exact results for them as part of their regular testing. |
|
MediaQuery can change a lot when things like the keyboard opens or screen resizes, I wouldn't risk it |
jonahwilliams
left a comment
There was a problem hiding this comment.
Approach LGTM, leave it up to @goderbauer to review the details.
goderbauer
left a comment
There was a problem hiding this comment.
Overall this LGTM.
Please leave a little more breadcrumbs in the docs so a future reader has an easier time understanding what the optimization is and why we did it.
There was a problem hiding this comment.
Maybe leave that as a comment here for future readers, who want to understand why we did this.
There was a problem hiding this comment.
I would just go with the assert here for now.
There was a problem hiding this comment.
nit: nit formatting here should be:
| final _TestInheritedElement ancestor = _TestInheritedElement( | |
| const Directionality( | |
| textDirection: TextDirection.ltr, child: Placeholder())); | |
| final _TestInheritedElement ancestor = _TestInheritedElement( | |
| const Directionality( | |
| textDirection: TextDirection.ltr, | |
| child: Placeholder(), | |
| ), | |
| ); |
There was a problem hiding this comment.
This and the next nit are still unaddressed.
goderbauer
left a comment
There was a problem hiding this comment.
LGTM with two remaining nits
There was a problem hiding this comment.
This and the next nit are still unaddressed.
Customer money is spending 20ms of startup time doing bookkeeping for
DirectionalityThis gets rid of that bookkeeping which makes updates faster, but Directionality should be changed infrequently. On some platforms change in text direction actually forces reloading the process anyways (iOS).Local testing of this change to the increase
stock_build_iteration2.5% (21ms).I tried to make this solution more general but there was apprehension to change the public API and it seemed like other Widgets didn't have the same draw as Directionality.
Examples of widgets using Directionality.of:
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.