Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance issues(missing frames) on LazyColum #4438

Open
xinzhengzhang opened this issue Mar 6, 2024 · 35 comments · Fixed by JetBrains/compose-multiplatform-core#1260
Open
Assignees

Comments

@xinzhengzhang
Copy link

xinzhengzhang commented Mar 6, 2024

Describe the problem

Bad performance on LazyColum( There is no problem with using Colum ) and the content of the screen does not move with the hand (latency)

  • Have you noticed any patterns or specific circumstances under which the problem occurs?
    In both implementations, I used the Instruments tool Allocation and Animation Hitches and Time Profiler.
    I also tried grab the metal profile. It's all subtle levels. It doesn't seem to be a gpu performance problem. I feel like it's still a cpu problem.
    The data performance of the two methods is basically the same, but the actual touch is obviously felt with LazyColum jank.

Affected platforms
Select one of the platforms below:

  • iOS

Versions

  • Kotlin version: 1.9.20
  • Compose Multiplatform version: 1.6.0
  • OS version(s) (required for Desktop and iOS issues): iOS 17.3.1
  • OS architecture (x86 or arm64): arm64
  • Device: iPhone 13

Sample code

// kotlin
fun getDemoViewController(isIdle: (Boolean) -> Unit): UIViewController {
    return ComposeUIViewController(
        content = {
            LazyColumn(userScrollEnabled = true, modifier = Modifier.fillMaxSize()) {
                items((0..100).toList(), { it }) { index ->
                    Text("Item $index", style = TextStyle(fontSize = 30.sp), modifier = Modifier.height(150.dp))
                }
            }

            // no problem using Column
//            Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
//                (0..100).forEach { index ->
//                    Text(
//                        "Item $index",
//                        style = TextStyle(fontSize = 30.sp),
//                        modifier = Modifier.height(150.dp)
//                    )
//                }
//            }

        }
    )
}

//swift
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()
    window?.rootViewController = UINavigationController(rootViewController: Compose_view_iosKt.getDemoViewController { _ in})
    window?.backgroundColor = .white
    return true
  }
}

Video
https://drive.google.com/file/d/1pekBo5D5OI-rkMHCb7byMYbAnsdXcz_c/view?usp=share_link

Profiling data
https://drive.google.com/drive/folders/1yndeXWYojDAoYxiZoraq-HVajq0HbbcX?usp=share_link

@igordmn
Copy link
Collaborator

igordmn commented Mar 7, 2024

Bad performance on LazyColum( There is no problem with using Colum)

@elijah-semyonov, could you check it on your device, when you have time? If we have a visible input lag with LazyColumn comparing to Column, it is worth to investigate/fix soon. I suspect a few things.

@igordmn igordmn added ios p:high High priority help wanted Extra attention is needed and removed submitted labels Mar 7, 2024
@kasem-sm
Copy link

kasem-sm commented Apr 1, 2024

Facing the same issue. The CPU consumption goes ~80% just with LazyColumn.

@elijah-semyonov
Copy link
Contributor

I'll have a look

@elijah-semyonov
Copy link
Contributor

Not related to performance, seems like a state update error, investigating further.

IMG_4575.MOV

@kasem-sm
Copy link

kasem-sm commented Apr 2, 2024

Facing the same issue. The CPU consumption goes ~80% just with LazyColumn.

Not related to this issue, sorry! But the scroll lag is visible.

@dangdo1
Copy link

dangdo1 commented Apr 9, 2024

Facing the same issue...

@kiethayqua
Copy link

Facing the same issue, and when start screen recording the scroll behavior so smooth

@kiethayqua
Copy link

@m-sasha before your PR will be reviewed and merged, how can I patch the dependency for my project ?

@m-sasha
Copy link
Contributor

m-sasha commented Apr 11, 2024

That would be difficult. Just wait for the first dev build after my PR is merged.

@kiethayqua
Copy link

@m-sasha thanks for your response

@tipsypotato
Copy link

tipsypotato commented Apr 18, 2024

Runs perfectly with the test at JetBrains/compose-multiplatform-core/pull/1260 but unfortunately the "visible jump" comes back when commenting out the LaunchedEffect(Unit) { ... }, it seems the while-loop in LaunchedEffect(Unit) { ... } results in something similar to screen recording on iOS, @m-sasha please have a furthur look.

@m-sasha
Copy link
Contributor

m-sasha commented Apr 18, 2024

@tipsypotato Not sure I understand. In my reproducer, the LaunchedEffect(Unit){...} is what is driving the scrolling. Without that it would not scroll.

Can you post a reproducer where the jump is still visible? Is it only visible on iOS? Can you post a video?

@tipsypotato
Copy link

@m-sasha Thanks for reply

the LaunchedEffect(Unit){...} is what is driving the scrolling.

Yeah but we can also scroll it mannually. I did some further tests, the scrolling experience with LazyColumn is still far from Column when scrolling on a real iOS device, it happened both on iPhoneSE3 and iPhone13 while run perfectly on Android.
You can check the iOS screen recording below:

Col-lazyCol.mov

reproducer code:

@Composable
fun TestLazyColumn() {
    Box(modifier = Modifier.fillMaxSize()) {
        Row {
            Column(
                modifier = Modifier
                    .fillMaxHeight()
                    .weight(1f)
                    .verticalScroll(rememberScrollState())
            ) {
                (0..100).forEach { index ->
                    Text(
                        "Column item $index",
                        style = TextStyle(fontSize = 30.sp),
                        modifier = Modifier.height(150.dp).fillMaxWidth().border(
                            width = 1.dp,
                            color = Color.Black
                        )
                    )
                }
            }


            LazyColumn(
                state = rememberLazyListState(),
                modifier = Modifier.fillMaxHeight().weight(1f)
            ) {
                items(100) { index ->
                    Text(
                        "LazyColumn item $index",
                        style = TextStyle(fontSize = 30.sp),
                        modifier = Modifier.height(150.dp).fillMaxWidth().border(
                            width = 1.dp,
                            color = Color.Black
                        )
                    )
                }
            }
        }
    }
}

@m-sasha
Copy link
Contributor

m-sasha commented Apr 19, 2024

@elijah-semyonov I guess more investigation is needed.

@elijah-semyonov
Copy link
Contributor

@m-sasha I'll have another look.

@elijah-semyonov
Copy link
Contributor

elijah-semyonov commented Apr 19, 2024

I struggle to reproduce it on 11 Pro Max and 14 Pro after the fix.
Can you use slomo camera from the other device to verify (to avoid observer effects such as ones that could be caused by screen recording)?

11_pro_max.mov
14_pro.mov

@jnelle
Copy link

jnelle commented Apr 22, 2024

I'm experiencing the same issue, along with an additional one. It will become apparent when you scroll up.
https://github.com/JetBrains/compose-multiplatform/assets/36324542/79224172-abda-4e08-b95d-8ce4f75a6487

@elijah-semyonov
Copy link
Contributor

@jnelle
Can you describe what you think you see? I'm not sure what to focus on exactly.

@m-sasha
Copy link
Contributor

m-sasha commented Apr 23, 2024

I think he means the list seems to scroll to a random far position sometimes.
But this is a different issue, possibly a bug in the user code. Please post a reproducer in a new issue.

@tipsypotato
Copy link

@elijah-semyonov In your second slomo video 14_pro.mov, the stutter happens at 0:09, 0:13, 0:23 and 0:26, and after several attempts with my reproducer, I noticed the stutter unexpectedly happens on Column when scrolling both at the sametime, while when scrolling the Column or the LazyColumn only, it seems the stutter only happens with LazyColumn.

@elijah-semyonov
Copy link
Contributor

@tipsypotato
Yeah, it's a debug build. Release build is much better (though can also have occasional stutters due to GC).
Can you check if you have this behavior on release builds?

@jnelle
Copy link

jnelle commented Apr 23, 2024

@elijah-semyonov I'm facing the performance issues when I scroll down and also when I scroll up the list skips random positions.

Here is the reproducible code:

         is UiState.Success -> {
                    LazyColumn(modifier = Modifier.padding(innerPadding)) {
                        items(count = (uiState as UiState.Success<MainFeedResponse>).data.clips.size) {
                            Card(
                                Modifier.fillMaxWidth(),
                                shape = RoundedCornerShape(16.dp),
                                ) {
                                Image(
                                    painter = rememberImagePainter(
                                        (uiState as UiState.Success<MainFeedResponse>).data.clips[it].image
                                    ),
                                    contentDescription = "image",
                                )
                                Text((uiState as UiState.Success<MainFeedResponse>).data.clips[it].title)

                            }

                        }
                    }

                }

You'll find the repository here:

https://github.com/Nelle-Bendlage-IT/MassengeschmackTV

@elijah-semyonov
Copy link
Contributor

@jnelle
Thanks, I'll have a look!

@jnelle
Copy link

jnelle commented Apr 23, 2024

@elijah-semyonov I'm also facing the performance (stutters) issues on my Pixel 6 Pro, but it could be possible that this is caused from debug build. But the scroll behavior is also wrong but not the same as one iOS.

video_2024-04-23_12-15-43.mp4

@elijah-semyonov
Copy link
Contributor

@jnelle
We don't have an ownership over Android implementation. Could you please file an issue to Google Compose Issue tracker and paste a link here?

@tipsypotato
Copy link

@tipsypotato Yeah, it's a debug build. Release build is much better (though can also have occasional stutters due to GC). Can you check if you have this behavior on release builds?

@elijah-semyonov It still happens with release build on iOS, the stutters are frequent and subtle, but still very noticeable compared to Column. Our project uses lots of LazyColumn, so it would be very appreciated if you could give it a further look!

@elijah-semyonov
Copy link
Contributor

elijah-semyonov commented Apr 29, 2024

@tipsypotato Apart from the issues you've noticed on my slowmo video, do you see something else? I'm trying to figure out if it's yet another lazy-column bug that we are not aware of (like the initially reported one), or general performance issues, which we are already working on.

@elijah-semyonov elijah-semyonov removed help wanted Extra attention is needed p:high High priority labels Apr 29, 2024
@tipsypotato
Copy link

@elijah-semyonov add the code below to TestLazyColumn in the reproduce code above, the lazy-column performance issue will be gone.

LaunchedEffect(Unit) {
    while (true) {
        withFrameMillis {}
    }
}

@MatkovIvan
Copy link
Member

@tipsypotato this code snippet makes me think that it's probably related to JetBrains/compose-multiplatform-core#1356

@xiaozhikang0916
Copy link
Contributor

@MatkovIvan As JetBrains/compose-multiplatform-core#1356 is merged, any chance to have a try with a dev-release?

@MatkovIvan
Copy link
Member

@xinzhengzhang
I've triggered CI for test build with this change - 0.0.0-jb-main-dev1635 should be ready in ~1h

@xinzhengzhang
Copy link
Author

@MatkovIvan Looks like 0.0.0-jb-main-dev1635 doesn't work and still performs well under workaround #4438 (comment)

@MatkovIvan
Copy link
Member

OK, so my guess was wrong.
@elijah-semyonov @m-sasha it looks like it requires a future inversion

@jnelle
Copy link

jnelle commented Jul 14, 2024

@elijah-semyonov I'm also facing the performance (stutters) issues on my Pixel 6 Pro, but it could be possible that this is caused from debug build. But the scroll behavior is also wrong but not the same as one iOS.

video_2024-04-23_12-15-43.mp4

This issue was my bad, I forgot to set the height for the Image which was inside the Box.

@okushnikov
Copy link

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet