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

Practical Performance Problem Solving in Jetpac...

Practical Performance Problem Solving in Jetpack Compose (By: Arslan Ali) - Google I/O Extended Lahore 2024

Talk by Arslan Ali (https://www.linkedin.com/in/arslan-ali-alvi/) at Google I/O Extended 2024 by GDG Lahore.

GDG Lahore

August 10, 2024
Tweet

More Decks by GDG Lahore

Other Decks in Programming

Transcript

  1. Road Map: •Introduction to Jetpack Compose •Lifecycle of Composables •How

    to scientifically detect performance issues? •Performance problem in Compose •Resolution of performance issues
  2. Introduction to Jetpack Compose Jetpack Compose is a modern, fully

    declarative UI toolkit developed by Google for building native Android applications. It simplifies and accelerates UI development on Android by eliminating the need for XML-based layouts and enabling developers to build UIs directly in Kotlin code.
  3. How to Scientifically Detect Performance Issues? In Order to scientifically

    detect performance issue we are using different tools and libraries: • Layout Inspecter • Macrobenchmark • Profile baseline • Perfetto
  4. Macrobenchmark Use the Macrobenchmark library for testing larger use cases

    of your app, including app startup and complex UI manipulations, such as scrolling a Scrollable or running animations.
  5. Baseline Profiles Baseline Profiles improve code execution speed by about

    30% from the first launch by avoiding interpretation and just-in-time (JIT) compilation steps for included code paths.
  6. Performance problem in compose •Doing expensive calculations in composable •Not

    using key in lazy layouts •Observing continuously changing state in composables •Navigational issue •Loading Heavy Composables •Heavy operations in main thread •Unnecessary subcompositions •Recomposition due to unstable parameters
  7. Doing expensive calculations in composable Composable functions can run very

    frequently, as often as for every frame of an animation. For this reason, you should do as little calculation in the body of your composable as you can.
  8. Not using key in lazy layouts Compose recomposes every item

    on the list, even though only one of them actually changed.
  9. Observing continuously changing state in composables One risk of using

    state in your compositions is that, if the state changes rapidly, your UI might get recomposed more than you need it to.
  10. Loading Heavy Composables The common painterResource composable function that loads

    an image from resources loads the image on the main thread during composition. This means that if your image is big, it can block the main thread with some work.
  11. Unnecessary Subcompositions The problem is that while Lazy layouts excel

    in layouts where you have much more items than the constrained size, they incur some additional cost, which is unnecessary when the lazy composition is not required.
  12. Stability in Compose Compose considers types to be either stable

    or unstable. A type is stable if it is immutable, or if it is possible for Compose to know whether its value has changed between recompositions. A type is unstable if Compose can't know whether its value has changed between recompositions. • Stable parameters: If a composable has stable parameters that have not changed, Compose skips it. • Unstable parameters: If a composable has unstable parameters, Compose always recomposes it when it recomposes the component's parent.
  13. Resolution of performance issues •Avoid expensive calculations in compose or

    use remember •Use Lazy layout keys •Use derivedStateOf to limit recompositions •Share data to other screens by using back stack entry •Accelerate heavy composables •Offload heavy operations to background thread •Remove unnecessary subcompositions •Always use stable parameters
  14. Avoid Expensive calculations in compose or use remember Now, the

    list is sorted once, when ContactList is first composed. If the contacts or comparator change, the sorted list is regenerated. Otherwise, the composable can keep using the cached sorted list.
  15. Use Lazy layout keys Providing a stable key for each

    item lets Compose avoid unnecessary recompositions. Compose can determine the item now at spot 3 is the same item that used to be at spot 2. Since none of the data for that item has changed, Compose doesn't have to recompose it.
  16. Use derivedStateOf to limit recompositions Derived state lets you tell

    Compose which changes of state actually should trigger recomposition. In this case, specify that you care about when the first visible item changes. When that state value changes, the UI needs to recompose, but if the user hasn't yet scrolled enough to bring a new item to the top, it doesn't have to recompose.
  17. Accelerate Heavy Composables • Use Coil's rememberAsyncImage composable, which loads

    the composable asynchronously. • The placeholder image had dimensions of 1600x1600px, which is clearly too big for what it shows. Changed it with vector and here are results:
  18. Always use stable parameters Because Contact is an immutable data

    class, Compose is sure that none of the arguments for ContactDetails have changed.So, Compose skips ContactDetails and does not recompose it.