https://kotlinlang.org logo
#compose
Title
# compose
d

Dave Scheck

02/01/2023, 8:03 PM
Does anybody have experience running compose on really old devices? We have a custom piece of hardware running Lollipop 5.1 that we're attempting to try compose on. Our goal is to see if compose is feasible and are seeing major performance issues. It seems like there is a ton of time spent in the Choreographer on the main thread while recomposition is taking place
Skipped 107 frames!  The application may be doing too much work on its main thread.
In this test I have a grid of Text objects that are all fed by the same value. The value is incremented once per second. Everything appears to update on screen properly and without jank, but our meager 1Ghz CPU is sitting at 92-94%. I took out the drawing parts and the app falls down to about 14% CPU. I've also noticed the layout inspector shows an odd component tree. Is there some compatibility magic going on to make compose work that's increasing the CPU load? I have tried building up a release build and there isn't much of an improvement there.
Copy code
ViewModel

    private val _value = MutableStateFlow(0)
    var value = _value.asStateFlow()
    private val _isRunning = MutableStateFlow(false)
    var isRunning = _isRunning.asStateFlow()

    fun start() {
        _isRunning.value = true
        viewModelScope.launch {
            while (_isRunning.value) {
                delay(1000)
                _value.value++
            }
        }
    }
Copy code
val screenViewModel: ScreenViewModel = hiltViewModel()
var value = screenViewModel.value.collectAsState().value

Column() {
  repeat(5) {
    Row(
      modifier = Modifier.fillMaxWidth(.95f),
      horizontalArrangement = Arrangement.SpaceEvenly,
      verticalAlignment = Alignment.CenterVertically
    ) {
         repeat(12) {
           Text("$value", style = TextStyle(color = Color.White))
          }
      }
   }
}
r

romainguy

02/01/2023, 8:21 PM
Are you testing release builds?
Ah sorry you answered that
r

rook

02/01/2023, 8:27 PM
Does the code you’ve provided reproduce the problem?
d

Dave Scheck

02/01/2023, 8:29 PM
No prob. That was one of the first thoughts that I had too when we saw the CPU utilization way outside of where we were expecting. We tried release builds and saw improvement but it hovers around 80%. @rook - Yes, that code is lifted right from the example. Here's the complete composable that has a wrapper column and some buttons, but those shouldn't impact much
Copy code
@Composable
fun HeavyCpuTestScreen(onBack: () -> Unit) {
    val screenViewModel: HeavyCpuTestScreenViewModel = hiltViewModel()
    var value = screenViewModel.value.collectAsState().value
    var isRunning = screenViewModel.isRunning.collectAsState().value
    Column(
        modifier = Modifier.background(Color(0xFF000000)),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceEvenly,
            verticalAlignment = Alignment.CenterVertically
        ) {
            ActionButton(label = "Stop", enabled = isRunning, onClick = screenViewModel::stop)
            ActionButton(label = "Start", enabled = !isRunning, onClick = screenViewModel::start)
        }
        Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.Bottom) {
            repeat(5) {
                Row(
                    modifier = Modifier.fillMaxWidth(.95f),
                    horizontalArrangement = Arrangement.SpaceEvenly,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    repeat(12) {
                        Text("$value", style = TextStyle(color = Color.White))
                    }
                }
            }
        }
        Spacer(modifier = Modifier.height(20.dp))
        ActionButton(label = "Exit", onClick = remember {
            {
                screenViewModel.stop()
                onBack()
            }
        })
    }
}
The spikes are the 1 second period in the CPU profiler
r

romainguy

02/01/2023, 8:44 PM
The fact that it’s periodic could point at the GC
d

Dave Scheck

02/01/2023, 8:46 PM
I see GC in the loggs, but it's not every value update period. I tried optimizing by moving the text style and value string outside the loops, but still no major breakthrough
Is there something in particular that you see in the code that would require a significant amount of GC?
I increased the period to 5 seconds and added a log each iteration. This log interestingly shows that the missed frames aren't every cycle. We still get the large spikes every 5 seconds when we recompose though
r

romainguy

02/01/2023, 10:53 PM
You should use the system profiler instead, it would give a better view of where time’s spent
d

Dave Scheck

02/01/2023, 11:25 PM
Are you referring to systrace? I'm following the instructions here https://developer.android.com/topic/performance/tracing/command-line but the version that I'm seeing locally requires Python 2.7. Is there a version that supports 3.10?
r

romainguy

02/02/2023, 12:07 AM
You can use Android Studio instead
System Trace in the profiler
Alternatively you can use https://perfetto.dev
z

Zoltan Demant

02/02/2023, 11:48 AM
Fwiw, there was a post earlier about grid with text performance being really bad and your setup seems very similar to what they were using.
d

Dave Scheck

02/02/2023, 2:48 PM
Zoltan - I did some searching and all I could find were threads about lazy grids and making sure to pass VM callbacks using delegation rather than direct lambdas since VMs are unstable. Is there something beyond that that you're referencing?
z

Zoltan Demant

02/02/2023, 2:56 PM
Sorry 😔 I saw that you mentioned grid in your post, but failed to realize that it consists of columns and rows. Please ignore my comment homer disappear
d

Dave Scheck

02/02/2023, 3:10 PM
No worries. Romain - I'm still struggling getting the system trace. Perfetto seems to fail due to an issue with ftrace. I'm not sure that our OS vendor optimized it out. Within Android Studio, I see a reduced set of options when profiling, but I see a full disabled list after I stop profiling and click on CPU. Is it possible that Lollipop isn't able to support those extra options or there's something missing in our OS?
v

vide

02/03/2023, 3:48 PM
Hey, I have experience running Compose on api level 22
d

Dave Scheck

02/03/2023, 3:49 PM
I'm very interested to hear about your experiences.
v

vide

02/03/2023, 3:49 PM
What version of compose.ui are you using?
d

Dave Scheck

02/03/2023, 3:50 PM
1.3.3
v

vide

02/03/2023, 3:50 PM
ok, you have hope 😄
There is a bug in versions above
1.3.0-alpha03
Try downgrading to that while I try to find the details...
(bug that specifically affects low api level compatibility layers)
The details are better documented in this issue: https://issuetracker.google.com/issues/260540794
In a nutshell there is a memory leak when using api 22 with 1.3.0-beta01 or higher. As a workaround we have pinned our compose.ui version to exactly
1.3.0-alpha03
and haven't discovered any other compability issues.
d

Dave Scheck

02/03/2023, 3:56 PM
Very interesting - In our case though we're not seeing a memory leak in this test (no memory really being allocated). Our issue seems to be with composition performance in the CPU domain
I'm building up a release version now to test out though
v

vide

02/03/2023, 3:59 PM
hm yeah, that might be a different issue then
I don't have time right now to look through the example code you're running, but I can say that it's definitely possible to run compose on quite old hardware on api level 22. If the CPU is super slow, it might become an issue that compose doesn't have multithreading support yet, which makes it perform a little worse than xml based UIs. But the difference isn't that dramatic for simple layouts
d

Dave Scheck

02/03/2023, 4:09 PM
While it seems a little better in the release build, it's still running way hotter than I would expect (75-80% vs consistently around 80%) so that bug may be having some sort of impact. There's still something else going on in the system though. There's a definite possibility that our processor just isn't going to cut it, but I want to make sure that we're not missing something before we stay stuck in the XML world. Thanks for your help. Please keep me posted if you think of anything else.
3 Views