Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Perfomance in a Compose World

Perfomance in a Compose World

In this talk, we will talk about some of the pitfalls and common mistakes we need to address to make sure our Compose code is not causing us recomposition, or performance problems!
We will focus on how to manage our code in the right way, so we can scope and launch our compose code to production without affecting our user experience

Session format
Talk (30 min)

Level
Intermediate

Dinorah Tovar

October 24, 2023
Tweet

More Decks by Dinorah Tovar

Other Decks in Technology

Transcript

  1. Performance in a

    Compose world
    Dinorah Tovar

    Google Developer Expert Android
    @ddinorahtovar
    @ddinorahtovar

    View full-size slide

  2. Recomposition
    Disclaimer: This talk is about
    ✨ Because performance has to do EVERYTHING
    with recomposition ✨
    @ddinorahtovar

    View full-size slide

  3. Compose aims for
    Perfomance
    Great
    @ddinorahtovar
    @Composable
    fun HelloWorld() {
    Text("Hello World")
    }

    View full-size slide

  4. Compose already give you some tips
    First of all - if you are having trouble with ur perfomance
    • Make sure you are doing the proper configuration in gradle
    • Debug mode is always slower that Release Mode + R8 enable
    • Do a macrobenchmark and optimize some flows
    • But first, you need to check if you are doing recomposition
    @ddinorahtovar

    View full-size slide

  5. Compose already give you some tips
    First of all - if you are having trouble with ur perfomance
    • But first, you need to check if you are doing too many recomposition
    @ddinorahtovar
    (maybe after the gradle)
    (maybe a little bit (not so little) too much

    View full-size slide

  6. Composition
    @ddinorahtovar

    View full-size slide

  7. @Composable fun view(data: Int)
    data: Int Composition
    emit
    Compositions shoots! 🥂
    @ddinorahtovar

    View full-size slide

  8. Compositions shoots! 🥂
    First Interaction Composition
    Insert “A”
    Insert “B”
    Second Interaction
    Re-composition
    @ddinorahtovar

    View full-size slide

  9. @ddinorahtovar
    @Composable
    fun SomeText() {
    var text by
    remember { mutableStateOf("") }
    TextField(
    value = text,
    onValueChange = { text = it }
    )
    }
    Field
    Input

    View full-size slide

  10. Composition

    Slot Table
    Composer
    Compose Runtime
    The composition is the state
    maintained by the memory
    Compose
    @ddinorahtovar

    View full-size slide

  11. Compose Runtime
    Composition

    Compose Runtime
    Slot Table
    Composer
    •Fundamental building blocks of
    Compose's programming model and
    state management, and core runtime
    for the Compose Compiler Plugin to
    target.
    •Handle everything for the states
    @ddinorahtovar

    View full-size slide

  12. Slot Table
    Composition

    Slot Table
    Composer
    Compose Runtime
    •Current state of the Composition
    •Updates with every composition
    •Gap Buffer - data structure
    •Positional Memorization
    @ddinorahtovar

    View full-size slide

  13. Composition

    Slot Table
    Composer
    Compose Runtime
    Unused Used B
    Used A
    Internal array
    Gap
    Collection
    Emit
    Collect B
    Collect A
    Slot Table
    @ddinorahtovar

    View full-size slide

  14. Composer
    •Reusable logic - for reusable purpose
    Composition

    Composer
    Compose Runtime
    Slot Table
    @ddinorahtovar

    View full-size slide

  15. @ddinorahtovar
    Composition

    Composer
    Compose Runtime
    Slot Table
    fun MultiMeasureLayout(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
    measurePolicy: MeasurePolicy
    ) {
    val materialized = currentComposer.materialize(modifier)
    val density = LocalDensity.current
    val layoutDirection = LocalLayoutDirection.current
    ReusableComposeNode>(
    factory = LayoutNode.Constructor,
    update = {
    set(materialized, ComposeUiNode.SetModifier)
    set(measurePolicy, ComposeUiNode.SetMeasurePolicy)
    set(density, ComposeUiNode.SetDensity)
    set(layoutDirection, ComposeUiNode.SetLayoutDirection)
    @Suppress("DEPRECATION")
    init { this.canMultiMeasure = true }
    },
    content = content
    )
    }

    View full-size slide

  16. @ddinorahtovar
    Composition

    Composer
    Compose Runtime
    Slot Table
    fun MultiMeasureLayout(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
    measurePolicy: MeasurePolicy
    ) {
    val materialized = currentComposer.materialize(modifier)
    val density = LocalDensity.current
    val layoutDirection = LocalLayoutDirection.current
    ReusableComposeNode>(
    factory = LayoutNode.Constructor,
    update = {
    set(materialized, ComposeUiNode.SetModifier)
    set(measurePolicy, ComposeUiNode.SetMeasurePolicy)
    set(density, ComposeUiNode.SetDensity)
    set(layoutDirection, ComposeUiNode.SetLayoutDirection)
    @Suppress("DEPRECATION")
    init { this.canMultiMeasure = true }
    },
    content = content
    )
    }

    View full-size slide

  17. @ddinorahtovar
    Composition

    Composer
    Compose Runtime
    Slot Table
    @Composable
    inline fun > ReusableComposeNode(
    noinline factory: () -> T,
    update: @DisallowComposableCalls Updater.() -> Unit,
    content: @Composable () -> Unit
    ) {
    if (currentComposer.applier !is E) invalidApplier()
    currentComposer.startReusableNode()
    if (currentComposer.inserting) {
    currentComposer.createNode(factory)
    } else {
    currentComposer.useNode()
    }
    currentComposer.disableReusing()
    Updater(currentComposer).update()
    currentComposer.enableReusing()
    content()
    }

    View full-size slide

  18. Give it a try!
    @ddinorahtovar

    View full-size slide

  19. Performance in a

    Compose world
    Dinorah Tovar

    Google Developer Expert Android
    @ddinorahtovar
    @ddinorahtovar

    View full-size slide