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

Android rendering performance and tools

Android rendering performance and tools

Rendering performance for android applications
in these slides you can find:
- how views are rendered in android
- which relevant tools we find to measure performance
- how compose render views
- what tools for compose we can find to measure performance
- tips for composable functions to improve performance

Paula Rosa

April 03, 2023
Tweet

More Decks by Paula Rosa

Other Decks in Technology

Transcript

  1. GPU - Rasterization • Strings, components (Buttons, RadioButton, Checkbox, etc),

    shapes -> to pixels • GPU is high consuming process • Display list: works as a cache strategy for the instances loaded in the gpu. • Calling invalidate makes this process more expensive in terms of performance
  2. GPU - Display List • List of commands to be

    executed in the GPU • These commands are saved once they are created GPU Button Valid displayList ? Execute display List yes no Record new display List Alert! Invalidate is called
  3. Invalidated vs Non-Invalidated • Change background • Change size •

    Change text • Change position in the layout • When you call invalidate method inside your custom view • All resources are pre-loaded in the GPU, so any resource used can help to not invalidate the view • Keeping resources (xml) to handle the changes (shapes for example) • Use clip to cut unnecessary part of views that are not visible for the user Invalidated called Invalidated not called
  4. Frames vs rendering (Android Smooth Transitions) 60 frames / second

    1000ms / 60 frames = 16.666 ms/frame Removed Frame Removed Frame You have 16ms to: • Computations and calculations • Draw views • Update views • Animations and transitions • Give time to GC collect everything that is needed GOOD LUCK !!!
  5. How to measure performance • Overdraw • GPU profiling tool

    Developer options Android Studio • LogCat • Layout Inspector
  6. How we treat rendering issues? • 1st: treat performance is

    not an easy task (keep this in mind) • Possible points to target: ◦ Check Overdraw ◦ Check which specific stage of rendering is demanding more work ◦ Check hierarchy
  7. Overdraw • How many times a view or part of

    view is being draw on top of another view / group view • Some overdraw might be expected, but we might be doing more than necessary • GPU costs are expensive, reducing overdraw might reduce this costs. Developer Options -> Debug GPU overdraw
  8. Overdraw - how to fix https://medium.com/androiddevelopers/draw-what-you-see-a nd-clip-the-e11-out-of-the-rest-6df58c47873e • Reduce unnecessary

    backgrounds • Flatten hierarchy • Clip to reduce views overlapping • Eliminate invisible views (if possible) • Reduce transparency https://www.lvguowei.me/post/android-custom-view-102-3/ https://developer.android.com/codelabs/advanced-android-kotlin-training-clipping-canvas-objects
  9. GPU Profiling tool 1 2 3 4 5 6 7

    8 Reduce draw logics Reduce draw work Too large / too many images Use Glide/Picasso Reduce hierarchy of views Check animators Reduce work / extract to another thread (onclick(), onLongClick(), onFocusChange(, onKeyListener() Reduce hierarchy of views
  10. Logcat Filter name What does Example TaskActivityManager Show the activity

    startup time Displayed com.paulacr.performance/androidx.compose.ui. tooling.PreviewActivity: +1s192ms Choreographer Show skipped frames Skipped 42 frames! The application may be doing too much work on its main thread. OpenGLRenderer Time consumption in GPU rendering Davey! duration=743ms; Flags=0, IntendedVsync=151198870863899, Vsync=151199570863871, (...) GpuCompleted=0,
  11. Rendering performance for Compose Extracted from https://developers.android.com/ • Not having

    xml does not mean that rendering problems ended • One of the problems for compose is the recomposition
  12. Recomposition Tree skipped skipped skipped skipped skipped • Any composable

    function has the ability to be re-invoked at anytime • Composable functions are re-invoked when the input changes • When recomposition happens it only calls the composables or lambdas that changed and skip the rest
  13. Layout inspector - Compose • Show recomposition count • Show

    skipped count • Allow to view the hierarchy in a better way • Can tell us where is a potential problem in our composable functions Skipped count Recomposition count
  14. Recomposition Compose attributes for functions Skippable: skip the function if

    all parameters are equal as before Restartable: restarting point Attributes for object instances Immutable Unstable Stable
  15. Stable vs Unstable type Stable type • Marked with annotation

    @Stable • Data classes with all “val” properties • Compose MutableState Unstable type • Mutable properties (var) • Collections: List, Set, Map, etc • Types from third parties libraries • All classes in non-compose project modules
  16. Composable metrics by Chris Banes subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions

    { if (project.findProperty("app.enableComposeCompilerReports") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + project.buildDir.absolutePath + "/compose_metrics" ] freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + project.buildDir.absolutePath + "/compose_metrics" ] } } } } ./gradlew assembleRelease -Papp.enableComposeCompilerReports=true build.gradle (root)
  17. Composable metrics { "skippableComposables": 57, "restartableComposables": 63, "readonlyComposables": 0, "totalComposables":

    63, "restartGroups": 63, "totalGroups": 67, "staticArguments": 34, … } app-release-module.json restartable skippable scheme("...") fun CatItemImmutable( stable cat: CatImmutable stable buttonText: String stable onClick: Function0<Unit> stable onItemClick: Function0<Unit> ) app-release-composables.txt Skippability
  18. Composable metrics stable class CatImmutable { stable val breed: String

    stable val color: Color stable val id: Int? <runtime stability> = Stable } unstable class CatMutable { stable val breed: String stable var color: Color <runtime stability> = Unstable } stability app-release-classes.txt app-release-classes.txt
  19. Changing stability @Stable data class CatMutable( val breed: String, @Stable

    var color: Color ) stable class CatMutable { stable val breed:String stable var color: Color }
  20. Lazy Layout Keys LazyColumn { items( items = notes, key

    = { note -> note.id} ) { note: Note -> NoteItem(item = note) { notes.remove(note) } } }
  21. DerivedStateOf • Used when the state change more than you

    want to update the UI val isValid = remember { derivedStateOf { typedEmail.value.contains("@") } }
  22. Useful references • Overdraw + GPU ◦ https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering ◦ https://chris.banes.me/posts/composable-metrics/

    ◦ https://youtu.be/zdQRIYOST64 (Google Io - how Android renders) ◦ https://developer.android.com/topic/performance/rendering/overdraw ◦ https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering • Clip Android Views ◦ https://medium.com/androiddevelopers/draw-what-you-see-and-clip-the-e11-out-of-the-r est-6df58c47873e ◦ https://www.lvguowei.me/post/android-custom-view-102-3/ ◦ https://developer.android.com/codelabs/advanced-android-kotlin-training-clipping-canvas -objects • Compose ◦ https://developer.android.com/jetpack/compose/performance/bestpractices ◦ https://youtu.be/6BRlI5zfCCk (compose runtime) ◦ https://youtu.be/ahXLwg2JYpc (compose performance tips) ◦ https://youtu.be/0yK7KoruhSM (compose rendering phases) ◦ https://youtu.be/BjGX2RftXsU (compose modifier deep dive) ◦ https://developer.android.com/jetpack/compose/graphics/images/optimization (images)