RecyclerView vs LazyColumn
Tags: android, ui, testing
Published: 2024-06-13 20:52:04

I've been working with Jetpack Compose for about 6-8 months but I've never checked a performance difference between both technologies, I only heard from Google that Compose is much better than XML View.

So, I decided to test a performance between RecyclerView and LazyColumn.

### About an app
The app solve a typical test task "List and details" :) The app was made in 2 variants (Compose and XML View) with the same UI. And we got a list of users from [GitHub REST API](https://docs.github.com/en/rest), and click by some user, and get details of user... _as usual..._

I don't use any optimization such as DiffUtil for RecyclerView or derivedStateOf for LazyColumn, I wanna see the difference as is. 

Let me don't upload screenshots of app, it's too boring. You may get the app from [GitHub Repository](https://github.com/MarDSoul/ttt-android-list-and-details.git)

For testing I use macrobenchmark library, device - Samsung Galaxy A04s (SM-A047F-14).

### Short results

|test|parameter|XML View|Jetpack Compose|
|-|-|-|-|
|`startup()`|timeToInitialDisplay (median)|769.5ms| 1048.0ms |
|`scrollReposList()`|frameDurationCpu (P99)|23.2ms|22.9ms|
||frameOverrun (P99)|19.8ms|23.6ms|
|`clickOnExpandedButton()`|frameDurationCpu (P99)|67,7ms|61.4ms|
||frameOverrun (P99)|~~766,1ms~~|72.8ms|
|`clickToDetails()`|frameDurationCpu (P99)|57,8ms|33.2ms|
||frameOverrun (P99)|~~2688,3ms~~|94.5ms|

OK, you may see that not all results are relevant. _Something went wrong..._
1st mistake in `clickOnExpandedButton()` I make by myself inside the `RecyclerView.Adapter` class. Sorry guys, I've just forgotten how to make a beautiful expanded action with RecyclerView.
2nd mistake in `clickToDetails()`... I don't know and we will just ignore this.

Let's see:
- `startup()`: cold boot by Compose is much worse than by XML - over than 20%
- `scrollReposList()`: frame durations are the same (difference is lesser than 10%); frame overrun - both values are positive and Compose is 20% worse. It means that Compose creates frame a little bit more faster but shows it on a screen more later. _Strange result. Needs to investigate... maybe later... maybe never :)_

Let's look a little deeper at frame rendering. And for compare I'll get the same moment from `clickToDetails()`. The moment when rendering list with repositories on the Details screen.

#### Rendering frame with Compose
![Rendering frame with Compose](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkht4l71m8ra9deich5k.png)

#### Rendering frame with XML View
![Rendering frame with XML View](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wpc4u50tx6nx6dxl3ye.png)

As we can see Compose shows UI more slower. A repos list - 91.27 ms of Compose against 71.95 ms of XML View. But there is an animation (15.38 ms) inside a Choreographer's synch in Compose.

### Conclusions
- There is a big difference in a cold boot. But it can be fixed with Baseline Profiles.
- We don't have a super, wow, amazing performance, but overall our app is a little bit more faster and smoothly with Compose.
- Too much depends directly on a developer and how he can optimize views or composable functions.
- Instrumented tests of XML View is really painful vs Compose.

_What do I want to say at the and? I want to use Compose so I never have to write instrumented tests for XML._