-
-
Notifications
You must be signed in to change notification settings - Fork 976
perf: Switch from forEach to regular for-loops for about 30% improvement in raw update performance #3472
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
Conversation
Ok, it looks like the benchmark GitHub action failed with Here are the results from the job run:
|
It can only run for members of the organization unfortunately. |
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.
One small nit, but LGTM already, Thanks for this!
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.
Lgtm! I thought we had already done this... I think there is a DCM rule that we can enable that checks for these.
I hope one day the compiler will be able to make forEach
et. al as efficient as normal loops.
I don't think we need DCM for this, I am pretty sure I saw a lint rule for that already somewhere...I will take a look for it |
Co-authored-by: Erick <erickzanardoo@gmail.com>
Thanks for the quick turnaround! FWIW, I don't think enabling a lint and then converting each and every |
Description
Replaces uses of
.forEach()
with regularfor
loops. This has significant impact on performance in hot paths such asComponent.updateTree()
andComponent.renderTree()
.In the graph above, you see 50 runs of
benchmark/update_components_benchmark.dart
. The forEach results are blue, the for-loop results are green. I could see this effect after just replacing theforEach
calls incomponent.dart
. Data here.I went ahead and replaced additional
forEach
calls elsewhere in the engine codebase, but there was no additional effect on the benchmark. Still, I kept those changes in. I only replacedforEach
in places that seemed relatively hot (e.g.ComponentSet.reorder()
). There are moreforEach
calls in the codebase but those seem fine to me as they aren't likely to be called too often.It should be noted that I needed to update the benchmark to add children to the components. Every
_BenchmarkComponent
now has 10 children. This feels a bit more realistic use of the framework than having a flat array of components with no children. By changing the benchmark code in this way, I made it a bit slower, so I'm not sure if the effect will be seen in the CI/CD.I also tried whether the change will have effect on my game's benchmark (which is a lot more involved and uses
flutter driver
to test the whole game in AOT mode). For the game, the effect is negligible but that was kind of expected since my game spends a significant amount of its CPU time on AI, raycasting, smoke simulation and drawVertices, none of which really depend on the speed of the engineupdate()
mechanism.Checklist
docs
and added dartdoc comments with///
.examples
ordocs
.Breaking Change?
Related Issues