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 impact when using in LazyColumn #520

Open
OlehHaidaienko opened this issue Oct 24, 2023 · 7 comments
Open

Performance impact when using in LazyColumn #520

OlehHaidaienko opened this issue Oct 24, 2023 · 7 comments
Labels
compose Jetpack Compose Issue

Comments

@OlehHaidaienko
Copy link

Please complete the following information:

  • Library Version [1.6.1]
  • Compose BoM [2023.10.01]

Describe the Bug:
When you're building a large screen and use LazyColumn with multiple Balloon you'll get performance impact - slight freeze during scrolling even on release build

Expected Behavior:

No performance reduction

Example

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val builder = rememberBalloonBuilder {
                        setArrowSize(10)
                        setArrowPosition(0.5f)
                        setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
                        setWidth(BalloonSizeSpec.WRAP)
                        setHeight(BalloonSizeSpec.WRAP)
                        setPadding(12)
                        setMarginHorizontal(12)
                        setCornerRadius(8f)
                        setBackgroundColor(Color(0xFF673AB7))
                        setBalloonAnimation(BalloonAnimation.ELASTIC)
                    }
                    LazyColumn(modifier = Modifier.fillMaxSize()) {
                        item(key = 1) { Item(builder = builder) }
                        item(key = 2) { Item(builder = builder) }
                        item(key = 3) { Section(color = Color.Blue, text = "Section #1") }
                        item(key = 4) { Section(color = Color.Magenta, text = "Section #2") }
                        item(key = 5) { Section(color = Color.Black, text = "Section #3") }
                        item(key = 6) { Section(color = Color.Gray, text = "Section #4") }
                    }
                }
            }
        }
    }

    @Composable
    private fun Section(color: Color, text: String) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(400.dp)
                .background(color = color)
        ) {
            Text(
                modifier = Modifier.align(Alignment.Center),
                text = text,
                color = Color.White
            )
        }
    }

    @Composable
    private fun Item(builder: Balloon.Builder) {
        Row(modifier = Modifier.fillMaxWidth()) {
            Spacer(modifier = Modifier.width(16.dp))
            Tooltip(builder = builder)
            Spacer(modifier = Modifier.weight(1F))
            Tooltip(builder = builder)
            Spacer(modifier = Modifier.weight(1F))
            Tooltip(builder = builder)
            Spacer(modifier = Modifier.width(16.dp))
        }
    }

    @Composable
    private fun Tooltip(builder: Balloon.Builder) {
        Box {
            Balloon(
                modifier = Modifier.align(Alignment.Center),
                builder = builder,
                balloonContent = {
                    Text(text = "Tooltip text", color = Color.White)
                }
            ) { balloonWindow ->
                Button(
                    onClick = {
                        balloonWindow.showAlignBottom()
                    }
                ) {
                    Text(text = "Show")
                }
            }
        }
    }
}
@skydoves skydoves added the compose Jetpack Compose Issue label Nov 3, 2023
@skydoves
Copy link
Owner

Hey @OlehHaidaienko, sorry for the late response. I'm wondering if this still happens with the latest version 1.6.3. Thanks!

@OlehHaidaienko
Copy link
Author

@skydoves Hi, unfortunately still reproducible on 1.6.3. Please check the screen recordings.
On the second screen recording, I just commented Balloon composable function
Tooltip enabled.webm
Tooltip disabled.webm

@eduardb
Copy link

eduardb commented Jan 4, 2024

Hi @skydoves, I've been also looking into some performance issues with Balloon tooltips in Compose, and one thing I noticed is that the Balloon composable takes a com.skydoves.balloon.Balloon.Builder argument which is considered unstable by the Compose compiler. See example report from the app I am working on:

restartable fun WithTooltip(
  stable showTooltipEffectKey: String
  unstable balloonBuilder: Builder
  stable balloonContent: Function2<Composer, Int, Unit>
  stable onTooltipShown: Function0<Unit>
  stable content: Function2<Composer, Int, Unit>
)

(generated using these instructions)

I am not sure how the builder is used internally, so I can't give any advice on how to solve this (e.g. if annotating with @Stable would help). Also I haven't done any profiling beyond this, so I can't tell for sure if this is the source of the performance issue, but I suspect that making the composable stable would help either way.

@skydoves
Copy link
Owner

skydoves commented Jan 4, 2024

Hey @eduardb, I don't think it's directly related to the stable marker, but I just released a snapshot version (1.6.5-SNAPSHOT), which annotates the Balloon.Builder as stable. You can import the snapshot version following this instruction: https://github.com/skydoves/Balloon?tab=readme-ov-file#snapshot

@SammYWin
Copy link

SammYWin commented Feb 19, 2024

I confirm also have the same problem, and it's actually pretty bad. I have a LazyColumn in my app and each item has two balloons for tooltips and scrolling even in release build gets SOO laggy. Once I remove the balloons - everything gets back to perfectly smooth scrolling. I guess maybe thats because of creating of the builder for each item even though it's remembered...I wanna try and see if I can create the builder just once for the entire app and provide it in items through the LocalComposition...
But yeah the problem is quiet severe and not obvious, It took me a few hours to realize it's because of the balloons

UPD:
Moving the creation of builder outside of each lazy item didnt help (I moved it on the screen level composition and provided down the item composable - just for a quick test if this will even work)
The snapshot version didn't fix the problem either

@JeremyThivet
Copy link

Hi,

I observed the same behavior in my application, updating to last version (1.6.5) didn't improve the performance issue. Have you eventually come up with a workaround @OlehHaidaienko ?

@OlehHaidaienko
Copy link
Author

@JeremyThivet Hi, for this case, I created a simple tooltip implementation based on Popup composable function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compose Jetpack Compose Issue
Projects
None yet
Development

No branches or pull requests

5 participants