Merged
Conversation
In most frames only the timer will be redrawn. By moving it into its own browser layer, we can reduce the amount of work the browser needs to do to redraw that layer. You can read more about this here: https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas#promote_elements_that_move_or_fade This improves our paint times from 0.71ms  to about 60us 
Collaborator
Author
|
I split out this PR from the other changes as this is a clear win, while the other changes don't seem to improve much (and possibly even regress the performance?!) |
CryZe
added a commit
to CryZe/livesplit-core
that referenced
this pull request
Jun 8, 2021
There are a lot of elements that are basically almost entirely static on the layout. Other elements such as the timer are frequently changing. In the browser we already noticed that by pushing the timer onto its own layer, you get a fairly big performance boost out of it. Here's that Pull Request: LiveSplit/LiveSplitOne#378 We want to apply a similar idea to the native renderer. In order to do this we first introduce flags in the layout state that mark whether a component or a part of a component is at the specific time considered frequently changing. By doing this not only does the native renderer benefit from it, but other renderers such as the web version can also make decisions based on that, as opposed to only applying the optimization to the timer component. With all the components providing these flags, the renderer can now split up the frame into a bottom layer and a top layer where all the frequently changing elements are rendered onto the top layer and all the other elements rendered onto the bottom layer. In fact the top layer is actually the frame buffer and it simply gets cleared by copying over regions from the bottom layer. That way there is no additional compositing necessary. Additionally the renderer is now more of a scene manager that manages entities in a scene rather than directly emitting draw calls to a backend. The scene is a data structure that allows traversing the two layers in any way a renderer (i.e. what used to be a backend) would want to render them out. So the whole design is a lot more decoupled now.
CryZe
added a commit
to CryZe/livesplit-core
that referenced
this pull request
Jun 9, 2021
There are a lot of elements that are basically almost entirely static on the layout. Other elements such as the timer are frequently changing. In the browser we already noticed that by pushing the timer onto its own layer, you get a fairly big performance boost out of it. Here's that Pull Request: LiveSplit/LiveSplitOne#378 We want to apply a similar idea to the native renderer. In order to do this we first introduce flags in the layout state that mark whether a component or a part of a component is at the specific time considered frequently changing. By doing this not only does the native renderer benefit from it, but other renderers such as the web version can also make decisions based on that, as opposed to only applying the optimization to the timer component. With all the components providing these flags, the renderer can now split up the frame into a bottom layer and a top layer where all the frequently changing elements are rendered onto the top layer and all the other elements rendered onto the bottom layer. In fact the top layer is actually the frame buffer and it simply gets cleared by copying over regions from the bottom layer. That way there is no additional compositing necessary. Additionally the renderer is now more of a scene manager that manages entities in a scene rather than directly emitting draw calls to a backend. The scene is a data structure that allows traversing the two layers in any way a renderer (i.e. what used to be a backend) would want to render them out. So the whole design is a lot more decoupled now.
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.


In most frames only the timer will be redrawn. By moving it into its own browser layer, we can reduce the amount of work the browser needs to do to redraw that layer.
You can read more about this here:
https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas#promote_elements_that_move_or_fade
This improves our paint times from 0.71ms
to about 60us