One Off the Slack: Compose and Performance
Some Android Developer asked:
Is Compose prone to problems similar to which a deeply nested Android ViewGroup suffers? I mean double layout taxation, slow measure/layout phases, etc. On Android, we always tried to build a flat view hierarchy, without deep nesting or weights. And what with Compose?
The original historical reason for the flat view hierarchy was to avoid running
into a StackOverflowError
— if the view hierarchy got to 10+ layers deep,
we might literally run out of stack space. Fortunately, we have a bigger stack
nowadays, so that particular concern has fallen away.
As Zach Klippenstein noted, Compose uses a single-pass layout system. Or, as Google’ Sean McQuillan noted in an earlier Slack thread:
It helped me build a mental model for compose layout to realize that it’s intended to be single pass and it works by modifying the (min, max) constraints passed to children… This takes some getting used to coming from Android views. The main advantage you get is that there’s no way to express non-performant O(2^n) UIs using
wrap_content
orlayout_weight
in Compose.
This does not mean that all performance problems are solved by magic. As Zach put it:
A slow layout is going to be slow no matter what, so if you have a really complex ConstraintLayout, it will be slower than a simple
Row
.
Or, as Google’s Romain Guy wrote:
Deep nesting means deeper call stacks, more code to execute, more state to track, potentially more complex drawing trees, more allocations, etc. No matter what, doing less is always going to beat doing more 🙂
The fact that Compose is function-based means that we can sometimes leverage
inline
functions to improve performance. dev16
should see inline
versions
of Row
and Column
, according to Google’s Leland Richardson, with significant gains as a result:
We saw around 6x improvement in a number of our benchmarks.
Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!