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

Elevating your App’s performance

Himanshu Singh
June 13, 2024
27

Elevating your App’s performance

With apps being developed at a rapid pace for diverse locales and users, it is crucial to continuously enhance app performance to provide an exceptional user experience. This talk will focus on strategies to improve app performance and empower developers to create high-performing apps. In this talk we will cover:Understanding the Baseline Profile, Explore how we practical approached to seamlessly integrate the Baseline Profile into a popular app with over 50 million downloads, How specific improvements were made during the critical user journey positively impacted app conversion rates, Let's understand the techniques to enhance the performance of Jetpack Compose layouts, Tips and Tricks for Boosting App Performance By the end of the talk, we will be equipped with practical knowledge and actionable strategies to power up their apps and enhance their performance.

Himanshu Singh

June 13, 2024
Tweet

Transcript

  1. Agenda. • Understanding why we need App performance. • How

    we can approach app performing good? • Integrating performance nitty grittier using Jetpack Compose. • Understanding Baseline profiles and improvements. @hi_man_shoe
  2. @hi_man_shoe Baseline Profile : 02 *.gradle benchmark { initWith buildTypes.release

    versionNameSuffix '+benchmark' signingConfig signingConfigs.debug matchingFallbacks = ['release'] debuggable false proguardFiles('baseline-profiles-rules.pro') }
  3. @hi_man_shoe Baseline Profile : 02 AndroidManifest.xml benchmark { initWith buildTypes.release

    versionNameSuffix '+benchmark' signingConfig signingConfigs.debug matchingFallbacks = ['release'] debuggable false proguardFiles('baseline-profiles-rules.pro') }
  4. @hi_man_shoe We need to setup any critical user flow that

    we want to improve the speed for! Baseline Profile
  5. @hi_man_shoe Base Setup for Generator @RunWith(AndroidJUnit4::class) abstract class BaselineProfileGeneratorScaffold {

    @get:Rule val rule = BaselineProfileRule() abstract fun MacrobenchmarkScope.invoke() @Test fun profileGenerator() { rule.collectBaselineProfile( packageName = PACKAGE_NAME, maxIterations = 15 ) { startActivityAndWait() invoke() } } }
  6. @hi_man_shoe Base Setup for Generator @RunWith(AndroidJUnit4::class) abstract class BaselineProfileGeneratorScaffold {

    @get:Rule val rule = BaselineProfileRule() abstract fun MacrobenchmarkScope.invoke() @Test fun profileGenerator() { rule.collectBaselineProfile( packageName = PACKAGE_NAME, maxIterations = 15 ) { startActivityAndWait() invoke() } } }
  7. @hi_man_shoe Base Setup for Generator @RunWith(AndroidJUnit4::class) abstract class BaselineProfileGeneratorScaffold {

    @get:Rule val rule = BaselineProfileRule() abstract fun MacrobenchmarkScope.invoke() @Test fun profileGenerator() { rule.collectBaselineProfile( packageName = PACKAGE_NAME, maxIterations = 15 ) { startActivityAndWait() invoke() } } }
  8. Execute. • Add Baseline profile grade plugin • ./gradlew :app:generateBaselineProfile

    • ./gradlew :app:generate{variant}BaselineProfile • Run on Release build always. @hi_man_shoe
  9. Device. @hi_man_shoe • Run on Rooted device • Gradle Manage

    Device with AOSP image • */src/release/generated/baselineProfiles
  10. @hi_man_shoe Create Release Branch Trigger CI for Baseline Profile Commit

    the generated Code Release Release process at NordVPN
  11. Stable/Unstable. • If a composable has stable parameters that have

    not changed, Recomposition won’t happen • If a composable has unstable parameters it will always recomposes itself when it re-composes the component's parent. @hi_man_shoe
  12. Stable Params • data class should be with val •

    We should not pass Collections / Observers • Pass Wrapper classes or Kotlin.Immutable collection or any custom classes. @hi_man_shoe
  13. @hi_man_shoe Compose Compiler Reports: subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions {

    if (project.findProperty("composeCompilerReports") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } if (project.findProperty("composeCompilerMetrics") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } } } }
  14. @hi_man_shoe Compose Compiler Reports: subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions {

    if (project.findProperty("composeCompilerReports") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } if (project.findProperty("composeCompilerMetrics") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } } } }
  15. @hi_man_shoe Compose Compiler Reports: subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions {

    if (project.findProperty("composeCompilerReports") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } if (project.findProperty("composeCompilerMetrics") == "true") { freeCompilerArgs += [ "-P", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + project.buildDir.absolutePath + "/compose_compiler" ] } } } }
  16. @hi_man_shoe Compose Compiler Reports: • module-class.txt : A report on

    the stability of classes in this • module-composables.txt : A report on how restartable and skippable the composables are. • module-composables.csv : A CSV Version of report.
  17. @hi_man_shoe composables.txt restartable scheme("[androidx.compose.ui.UiComposable]") fun ServerList( stable index: Int unstable

    servers: List<Servers> stable OnServerClick: Function1<Long, Unit> stable modifier: Modifier? = @static Companion )
  18. @hi_man_shoe composables.txt restartable scheme("[androidx.compose.ui.UiComposable]") fun ServerList( stable index: Int unstable

    servers: List<Servers> stable OnServerClick: Function1<Long, Unit> stable modifier: Modifier? = @static Companion )