Is having janky frames normal with Jetpack Compose...
# compose
a
Is having janky frames normal with Jetpack Compose? I build two test apps, one in Compose and one in XML with a TabLayout + HorizontalPager and a GridView with 3 Columns. I recorded the stacktrace of both apps and uploaded it to Perfetto. The one with many janky frames is jetpack compose. The lags appear while swiping through the HorizontalPager, scrolling through the LazyVerticalGrid is working fine. I think I either have to stop using HorizontalPager + LazyVerticalGrid or switch back to XML. Any ideas what could cause this many janky frames? Code is in Thread ->
Scrollable TabRow + HorizontalPager:
Copy code
val tabList = listOf("Following", "Trending", "New", "Top", "Most Shared", "Most Saved", "All")
val pagerState: PagerState = rememberPagerState(initialPage = 1)
val coroutineScope = rememberCoroutineScope()

Column(
    modifier = Modifier
        .fillMaxSize()
        .background(MaterialTheme.colors.background)
) {
    ScrollableTabRow(
        modifier = Modifier.fillMaxWidth(),
        backgroundColor = MaterialTheme.colors.surface,
        contentColor = Color.White,
        edgePadding = 8.dp, 
        selectedTabIndex = pagerState.currentPage, 
        indicator = { tabPositions ->
            TabRowDefaults.Indicator(
                Modifier.pagerTabIndicatorOffset(pagerState, tabPositions),
                color = MaterialTheme.colors.primary
            )
        }
    ) {
        // Add tabs for all of our pages
        tabList.forEachIndexed { index, title ->
            Tab(
                text = { Text(title) },
                selected = pagerState.currentPage == index,
                onClick = {
                    coroutineScope.launch {
                        pagerState.animateScrollToPage(index)
                    }
                },
            )
        }
    }

    HorizontalPager(
        state = pagerState,
        count = tabList.size
    ) { page: Int ->
        when (page) {
            0 -> MyList()
            1 -> MyList()
            2 -> MyList()
            3 -> MyList()
            4 -> MyList()
            5 -> MyList()
            6 -> MyList()
        }
    }
MyList:
Copy code
@Composable
fun MyList(){
    LazyVerticalGrid(
        modifier = Modifier.fillMaxSize(),
        columns = GridCells.Fixed(3),
        content = {
            items(100) { item ->

                Button(onClick = { /*TODO*/ }) {
                    Text(text = "Hello")
                }
            }
        })


}
Performance is okay but by far not as smooth as with XML, the problem is that I need to put a lot more into the items than just a Button saying “Hello” 😅 For my app I need per item: 1x 512x512 Image 2x TextView 2x Icons 1x Card with elevation If I try to implement that it is performing really really bad, eventhough I’m running in release
I have the strong feeling it simply has something todo with HorizontalPager library from accompanist.
r
a
@romainguy I read through this 3 times in the last 2 weeks 😁
r
Release alone doesn’t “fix” everything since so much code needs to be JITted (that’s where baseline profiles come in, in prod)
There’s a way to force AOT compilation, I’m trying to find you a page that explains how to do it
adb shell cmd package compile -m speed -f my-package
a
Yes I din’t took a deep dive into Baseline Profiles yet, gonna try it out, thank you
r
The main difference between Compose and Views is that Views are part of the phone’s system image and pre-compiled, so they never go through a JIT phase
a
But can baselines profiles also speed up the overall app performance? I though it’s for making the app launch more fast
r
It helps startup times but also performance in the beginning since there’s no interpreter->JIT involved (at least for the code covered by baseline profiles)
a
But my HorizontalPager is performing bad all the time, even 5 minutes after app startup
My app is performing really good overall, only when swiping the HorizontalPager the FPS starts to drop
i
I’d also recommend at least Android Studio Dolphin, as it includes AGP 7.3.0-rc01. Chipmunk has 7.2.2, but that generates a v1 profile. With no baseline profile, the device has to build up a profile of which code paths are important, so it can take ~days to get the AOT benefits. The baseline profile lets you get a lot of that benefit right away. When it’s tune right, you get benefit both in startup and regular app use, so I’d highly recommend starting with that before measuring more
b
How does it perform if you just have Text in the cell instead of Buttons?
I have just run this myself and the button change didn't help. I can confirm though that something isn't right, it's very janky. I will look into it
a
Its starting the app, waiting for the HorizontalPager to load and swipe right to the next page
Unfortunately there is no visible change when running the app in release build. I have my baseline-prof.txt file inside the main folder next to Manifest. Am I missing something? Are the changes only visible when installing through google play?
i
The percentiles represent how many instances were better than that. For example p50 means 50% of measurements were better than the given number, so you can think of p50 as “typical performance.” Something like p95 shows you the number 95% are better than, so it’s more “when things are slow, how slow are they?” In a very general sense, you want p50 to be very good because that’s the most common experience, but you also keep an eye on the p90/p95/p99 to understand how bad it can be. Here, all the numbers look bad, but if p50 frameDurationCpuMs were 5ms and p95 were 100ms, that would tell you “this is typically really smooth but sometimes it drops a lot of frames.” For the baseline profile, AGP should mostly do this for you (you can always tune it for your specific app, but the Compose baseline profile should give good out-of-the-box performance). I’d first make sure you’re using AGP 7.3.0-rc01 or newer because there are a few issues in previous versions. If you are, you can open the production APK just like a zip and look for assets/dextop/baseline.profm. The start of that file should be “prm002" to indicate it’s a baseline profile v2, which will work across Android versions.
a
@Ian G. Clifton Okay thank you very much, but for Google Play I can generate an app bundle or do I have to upload the release.apk into Google Play? Also whats the difference between installing through Google Play and installing the .apk on the local device? Why are baseline profiles automatically activated when installing through Google Play but I have to manually sideload them when installing the .apk locally? How does that work? What is Google Play doing?
i
For Google Play, you can upload either. Play automatically checks the APK for an included baseline profile and metadata file. If it sees both, then it generates the applicable baseline profile versions for each different Android OS version. When a given device downloads an APK via Play, the profile for that device’s specific OS is downloaded as well; the APK is unpacked and then the profile is used to generate the AOT’ed code during the install process. There isn’t an equivalent adb command that does all these steps
621 Views