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. Recomposition Disclaimer: This talk is about ✨ Because performance has

    to do EVERYTHING with recomposition ✨ @ddinorahtovar
  2. 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
  3. 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
  4. @ddinorahtovar @Composable fun SomeText() { var text by remember {

    mutableStateOf("") } TextField( value = text, onValueChange = { text = it } ) } Field Input
  5. Composition 
 Slot Table Composer Compose Runtime The composition is

    the state maintained by the memory Compose @ddinorahtovar
  6. 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
  7. Slot Table Composition 
 Slot Table Composer Compose Runtime •Current

    state of the Composition •Updates with every composition •Gap Buffer - data structure •Positional Memorization @ddinorahtovar
  8. Composition 
 Slot Table Composer Compose Runtime Unused Used B

    Used A Internal array Gap Collection Emit Collect B Collect A Slot Table @ddinorahtovar
  9. @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<LayoutNode, Applier<Any>>( 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 ) }
  10. @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<LayoutNode, Applier<Any>>( 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 ) }
  11. @ddinorahtovar Composition 
 Composer Compose Runtime Slot Table @Composable inline

    fun <T : Any?, reified E : Applier<*>> ReusableComposeNode( noinline factory: () -> T, update: @DisallowComposableCalls Updater<T>.() -> Unit, content: @Composable () -> Unit ) { if (currentComposer.applier !is E) invalidApplier() currentComposer.startReusableNode() if (currentComposer.inserting) { currentComposer.createNode(factory) } else { currentComposer.useNode() } currentComposer.disableReusing() Updater<T>(currentComposer).update() currentComposer.enableReusing() content() }