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

io22 extended What's new in app performance

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

io22 extended What's new in app performance

20220611 구글 스타트업 캠퍼스
2022 IO Extended Korea Android 에서
What's new in app performance 주제로 발표한 자료입니다.
https://www.youtube.com/watch?v=1TsQ0buZUas

Avatar for Veronikapj

Veronikapj

June 11, 2022

More Decks by Veronikapj

Other Decks in Programming

Transcript

  1. Why? 30 % 2.4 % ࡈۄ૓ জ द੘ दр Ѩ࢝

    ૐо Source: goo.gle/3JCc453
  2. ੉Ѫ਷ ޖ঺ ੌөਃ? ٜযоӝী খࢲ “জ੄ द੘ਸ ୭੸ച ೞҊ, ߡߢѢܿਸ

    ઴੉ݴ ୭ઙ ࢎਊ੗ ࢿמਸ ѐࢶೡ ࣻ ੓ب۾ ೞח ೐۽೙ ӝ߈ ୭੸ച(PGO, Profile Guided Optimization)੄ ೠ ഋకੑפ׮.” https://forms.gle/MSzZ53RQ3jH6Qm758
  3. 1. Macrobenchmark 2. Baseline Profiles 3. Microbenchmark 4. Android Profiler

    ٜযоӝী খࢲ “জ੄ द੘ਸ ୭੸ച ೞҊ, ߡߢѢܿ ਸ ઴੉ݴ ୭ઙ ࢎਊ੗ ࢿמਸ ѐࢶೡ ࣻ ੓ب۾ ೞח ೐۽೙ ӝ߈ ୭੸ച (PGO, Profile Guided Optimization)੄ ೠ ഋకੑפ׮.”
  4. Baseline Profiles stable androidx.profileinstaller:profileinstaller:1.1.0 ޷ܻ ٜ݅য فח App profiles Startup

    दр хࣗ & Jank хࣗ https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  5. জ ߂ ۄ੉࠳۞ܻীࢲ custom profile rule ઁҕ Startup ߂ jack

    performance ೱ࢚ ੋӝ ੓ח Jetpack librariesী profile ୶о Baseline Profiles https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  6. h tt ps://github.com/android/sun fl ower Sunflower పझ౟ प೯ ߂ ৮ܐ

    -> ೐۽೙ ࢤࢿ ls /storage/emulated/0/Android/media/app.name Sample_startup-baseline-prof.txt ੉ܴਸ baseline-prof.txtਵ۽ ߸҃೧ࢲ app/src/main ߃ী ਤ஖ Baseline Profile
  7. ۄ੉࠳۞ܻ৬ গ೒ܻா੉࣌਷ ৔ೱਸ ӓ؀ചೞח ୭ࣗೠ੄ ೐۽೙ ӏ஗ਸ ੿੄ (Size <

    1.5 MB) 
 গ೒ܻா੉࣌੄ ցޖ ݆਷ ࠗ࠙ਸ ஹ౵ੌೞח ҟߧਤೠ ӏ஗਷ ٣झ௼ ঘࣁझ പࣻо טӝ ٸޙী द੘ ࣘبܳ וܻѱ ٜ݅ ࣻ ੓णפ׮. যڃ ӝળਵ۽ Baseline Pro fi leਸ ࢸ੿ೡ Ѫ ੋ૑ ߈٘द పझ౟೧ࢲ ੸ਊೞח Ѫ੉ જणפ׮. Q & A সؘ੉౟ ੸ਊ दী Ҋ۰೧ঠ ೡ Ѫ https://developer.android.com/studio/pro fi le/baselinepro fi les
  8. App Startup stable androidx.startup:startup-runtime:1.1.1 জ द੘ द ҳࢿਃࣗܳ ୡӝചೞח ߑߨ

    ઁҕ द੘ ࣽࢲ рࣗച, ୡӝച ࣽࢲ ݺद੸ਵ۽ ࢸ੿ https://developer.android.com/topic/libraries/app-startup
  9. জ द੘ ઺ ܻࣗझ ҃೤ ߑ૑(Avoid resource contention ) Ҋࢿמ

    ஹನք౟ ୡӝച(Performant component initialization) App Startup https://youtu.be/DYdHLqLVspY IO 22 What’s new in App performance
  10. class SyncRepoInitializer : Initializer<SyncRepo> { override fun create(context: Context): SyncRepo

    { return SyncRepo(WorkManager.getInstance(context)) } override fun dependencies() : List<Class<out Initializer<*>>> { return listOf(WorkManagerInitializer::class.java) } } https://youtu.be/DYdHLqLVspY IO 22 What’s new in App performance
  11. class SyncRepoInitializer : Initializer<SyncRepo> { override fun create(context: Context): SyncRepo

    { return SyncRepo(WorkManager.getInstance(context)) } override fun dependencies() : List<Class<out Initializer<*>>> { return listOf(WorkManagerInitializer::class.java) } } https://youtu.be/DYdHLqLVspY IO 22 What’s new in App performance
  12. <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- This entry makes SyncRepoInitializer

    discoverable. --> <meta-data android:name="com.example.SyncRepoInitializer" android:value="androidx.startup" /> </provider> https://developer.android.com/topic/libraries/app-startup AndroidManifest.xml
  13. ӝࠄ ਊয ੿ܻ https://www.youtube.com/watch?v=0adLO2VRJtc IO 21 Macrobenchmark۽ ߡߢѢܿ ߂ झఋ౟স

    ஏ੿ 60Hz ചݶী झ௼܀, ੹ജ, গפݫ੉࣌ ١੄ ਑ ૒੐੉ ੓ਵݶ জীࢲ ࢜۽ Ҋஜ ࣘبী ݏ ѱ ୡ׼ 60೐ۨ੐ਸ ࢤࢿ Jank? জ੉ ചݶਸ ࢜۽ Ӓܻݶࢲ ߊࢤೞח ߡߢѢܿ੉ա ݥ୺ਸ ੄޷
  14. ӝࠄ ਊয ੿ܻ https://www.youtube.com/watch?v=0adLO2VRJtc IO 21 Macrobenchmark۽ ߡߢѢܿ ߂ झఋ౟স

    ஏ੿ 60Hz ചݶী झ௼܀, ੹ജ, গפݫ੉࣌ ١੄ ਑ ૒੐੉ ੓ਵݶ জীࢲ ࢜۽ Ҋஜ ࣘبী ݏ ѱ ୡ׼ 60೐ۨ੐ਸ ࢤࢿ Jank? জ੄ ೐ۨ੐ ࢤࢿ ࣘبо ցޖ ןযࢲ ࢤӣ
  15. ࠙ࢳ ੿ࠁী݅ ੄૑ೡ ࣻ হ਺ . ׮নೠ ૑಴о ੓૑݅ प

    ࢎਊ ૑಴ח ࡈܻ ঳ਸ ࣻ হ਺. Metrics from the field are not enough 01 Existing Benchmark library is limited 02 ࠛউ੿ೞѢա, प೯ೡ loopо ߸زغѢ ա दझమ੉ ࠂ੟ೞҊ ֢੉ૉо ݆Ѣա ৢ߄ܰѱ ࢸ੿ೞӝ য۰਎ ࣻ ੓਺. Stable Measurement is not easy 03 ٜযоӝী খࢲ “জ ࢿמ ѐࢶ੉ য۰ਕਃ” ӝઓ੄ Jetpack benchmarking ۄ੉ ࠳۞ܻח জ द੘੉ա Jank ܳ ஏ੿ೡ ࣻ হ਺ . MicroBenchmarkח ؀׮ࣻ ࢎਊ ࢎ۹ ী ੸ਊغ૑ ঋ਺. द੘ दр ؀न CPU ܳ ஏ੿ https://www.youtube.com/watch?v=0adLO2VRJtc IO 21 Macrobenchmark۽ ߡߢѢܿ ߂ झఋ౟স ஏ੿
  16. Macrobenchmark stable androidx.benchmark:benchmark-macro:1.1.0 ੿ഛೠ App Startup ஏ੿ Scrolling ࢿמ ஏ੿

    Locally & CI https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  17. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) }
  18. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) }
  19. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) } Metric StartupTimingMetric জ द੘ दр ஏ੿ FrameTimingMetric п ೐ۨ੐ ఋ੉߁ ੿ࠁ
  20. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) }
  21. StartupBenchmarks.kt @Test fun startupCompilationNone() = startup(CompilationMode.None()) @Test fun startupCompilationPartial() =

    startup(CompilationMode.Partial()) @Test fun startupCompilationWarmup() = startup(CompilationMode.Partial(BaselineProfileMode.Disable, 2))
  22. StartupBenchmarks.kt @Test fun startupCompilationNone() = startup(CompilationMode.None()) @Test fun startupCompilationPartial() =

    startup(CompilationMode.Partial()) @Test fun startupCompilationWarmup() = startup(CompilationMode.Partial(BaselineProfileMode.Disable, 2))
  23. CompilationMode.kt @Test fun startupCompilationPartial() = startup(CompilationMode.Partial()) @RequiresApi(24) class Partial @JvmOverloads

    constructor( val baselineProfileMode: BaselineProfileMode = BaselineProfileMode.Require, / . . . / ) : CompilationMode() { ... }
  24. @Test fun startupCompilationNone() = startup(CompilationMode.None()) @Test fun startupCompilationPartial() = startup(CompilationMode.Partial())

    @Test fun startupCompilationWarmup() = startup(CompilationMode.Partial(BaselineProfileMode.Disable, 2)) StartupBenchmarks.kt Compilation Mode None জ੉ ࢎ੹ ஹ౵ੌ غ૑ ঋ਺ (Worst Case) Full п জ੉ ৮੹൤ ࢎ੹ ஹ౵ੌ ؽ. (Ideal Case) Partial о੢ അप੸ੋ জ ࢸ஖ ജ҃
  25. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) }
  26. StartupBenchmarks.kt private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(StartupTimingMetric()), iterations = 5, compilationMode = compilationMode, startupMode = StartupMode.COLD, setupBlock = { pressHome() } ) { startActivityAndWait() // wait for the content called by reportFullyDrawn is visible val recyclerHasChild = By.hasChild(By.res(packageName, "garden_list")) device.wait(Until.hasObject(recyclerHasChild), 5_000) } Startup Mode Hot ݫݽܻী ੓ח Ѧ۽ Activity ׮द द੘ Warm ӝઓ ೐۽ࣁझ ղীࢲ Activityܳ ࢤࢿ द੘ Cold प೯ ઺੉ ইצ ೐۽ࣁझীࢲ द੘ ੹୓ ೐۽ࣁझ ୡӝച
  27. h tt ps://github.com/android/sun fl ower StartupBenchmarks_startupCompilationWarmup timeToFullDisplayMs min 185.4, median

    210.2, max 222.5 timeToInitialDisplayMs min 172.1, median 196.0, max 204.3 Traces: Iteration 0 1 2 3 4 StartupBenchmarks_startupCompilationPartial timeToFullDisplayMs min 197.5, median 208.5, max 265.6 timeToInitialDisplayMs min 185.8, median 196.1, max 246.4 Traces: Iteration 0 1 2 3 4 StartupBenchmarks_startupCompilationNone timeToFullDisplayMs min 296.1, median 302.1, max 317.3 timeToInitialDisplayMs min 280.6, median 284.4, max 296.9 Traces: Iteration 0 1 2 3 4 StartupTimingMetric Sunflower
  28. timeToInitialDisplayMs timeToFullDisplayMs Launch intent ࣻनೠ റ first frame ਸ Ӓܻחؘ

    ө૑੄ दр Launch intent ࣻनೠ റ android.app.Activity.reportFullyDrawn ө૑੄ दр StartupTimingMetric https://developer.android.com/studio/pro fi le/macrobenchmark-metrics
  29. PlantListBenchmarks.kt private fun openPlantList(compilationMode: CompilationMode) = benchmarkRule.measureRepeated( packageName = PACKAGE_NAME,

    metrics = listOf(FrameTimingMetric()), compilationMode = compilationMode, iterations = 5, startupMode = StartupMode.COLD, setupBlock = { pressHome() // Start the default activity, but don't measure the frames yet startActivityAndWait() } ) { goToPlantListTab() }
  30. frameOverrunMs frameDurationCpuMs Frame੉ ӝળࠁ׮ וܽ ੿ب CPUীࢲ ೐ۨ੐ਸ ࢤࢿೞחؘ Ѧܽ

    दр (UI thread, RenderThread ನೣ) FrameTimingMetric https://developer.android.com/studio/pro fi le/macrobenchmark-metrics + : Drop ػ Frame, Jank - : Deadlineࠁ׮ ঴݃ա ࡅܲ૑ Android 12+
  31. h tt ps://github.com/android/sun fl ower Sunflower FrameTimingMetric PlantListBenchmarks_plantListCompilationPartial frameDurationCpuMs P50

    6.5, P90 26.5, P95 50.3, P99 60.7 Traces: Iteration 0 1 2 3 4 PlantListBenchmarks_plantListCompilationFull frameDurationCpuMs P50 9.5, P90 32.7, P95 51.6, P99 63.2 Traces: Iteration 0 1 2 3 4 Timed out waiting for process (com.google.samples.apps.sunflower.macrobenchmark) to appear on lge- lm_v500n-LMV500N68592ec6. PlantListBenchmarks_openPlantList frameDurationCpuMs P50 22.2, P90 50.1, P95 82.1, P99 100.4 Traces: Iteration 0 1 2 3 4 LM-V500M(Android 11)
  32. h tt ps://github.com/android/sun fl ower Sunflower FrameTimingMetric PlantListBenchmarks_plantListCompilationFull frameDurationCpuMs P50

    16.3, P90 31.8, P95 35.8, P99 69.4 frameOverrunMs P50 1.9, P90 17.5, P95 20.5, P99 38.4 Traces: Iteration 0 1 2 3 4 PlantListBenchmarks_openPlantList frameDurationCpuMs P50 29.4, P90 56.5, P95 161.2, P99 178.6 frameOverrunMs P50 16.8, P90 41.8, P95 59.0, P99 181.8 Traces: Iteration 0 1 2 3 4 Google Pixel 3a(Android 12)
  33. పझ౟ ജ҃ ( ௏٘ա ٣߄੉झ झಖ ژח ীޯۨ੉ఠ )ী ٮۄ

    ׮ܲ ࣻ஖о աৢ ࣻ ੓ח ࠗ ࠙ੑפ׮. ٮۄࢲ ׮নೠ ജ҃ীࢲ ࣻ஖ܳ ࠺Ү೧ࠄ റী п੗੄ ӝળਸ ੿ೞҊ ѐࢶ ನੋ౟ ܳ ੟ইաоח ؘী ࢎਊೞݶ જਸ Ѫ эणפ׮. Q & A সؘ੉౟ ࣻ஖ܳ ࠅ ٸ.. https://developer.android.com/studio/pro fi le/baselinepro fi les
  34. API 23ө૑ ૑ਗ TraceSectionMetricਸ ࢎਊ೧ࢲ custom trace-based timing ஏ੿ ୶о

    AudioUnderrunMetricਵ۽ য়٣য় ӝ߈ х૑ ೲਊ ઱ ࢎਊ ҃۽(Critical workflows)ী ؀ೠ ೐۽೙ਸ ࢤࢿ - BaselineProfileRule ୶о Macrobenchmark https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  35. https://developer.android.com/studio/pro fi le/jankstats class JankLoggingActivity : AppCompatActivity() { private lateinit

    var jankStats: JankStats override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // metrics state holder can be retrieved regardless of JankStats initialization val metricsStateHolder = PerformanceMetricsState.getForHierarchy(binding.root) // initialize JankStats for current window jankStats = JankStats.createAndTrack( window, Dispatchers.Default.asExecutor(), jankFrameListener, ) // add activity name as state metricsStateHolder.state?.addState("Activity", javaClass.simpleName) // ... }JankLoggingActivity.kt
  36. class JankAggregatorActivity : AppCompatActivity() { private lateinit var jankStatsAggregator: JankStatsAggregator

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // Metrics state holder can be retrieved regardless of JankStats initialization. val metricsStateHolder = PerformanceMetricsState.getForHierarchy(binding.root) // Initialize JankStats with an aggregator for the current window. jankStatsAggregator = JankStatsAggregator( window, Dispatchers.Default.asExecutor(), jankReportListener ) // Add the Activity name as state. metricsStateHolder.state?.addState("Activity", javaClass.simpleName) }JankAggregatorActivity.kt https://developer.android.com/studio/pro fi le/jankstats
  37. https://developer.android.com/studio/pro fi le/jankstats override fun onResume() { super.onResume() jankStatsAggregator.jankStats.isTrackingEnabled =

    true } override fun onPause() { super.onPause() // Before disabling tracking, issue the report with (optionally) specified reason. jankStatsAggregator.issueJankReport("Activity paused") jankStatsAggregator.jankStats.isTrackingEnabled = false }JankAggregatorActivity.kt
  38. https://developer.android.com/studio/pro fi le/jankstats *** Jank Report (Activity paused), totalFrames =

    170, jankFrames = 26 FrameData( frameStartNanos=257993674283620, // frame द੘ दр frameDurationUiNanos=77057961, //frame ૑ࣘ दр frameDurationCpuNanos=80083690, isJank=true, // Jank = അ੤ refresh rate ࠁ׮ ۪؊݂ೞח ؘ ف ߓо Ѧܻח frame states=[RecyclerView: Settling, Activity: JankAggregatorActivity] ) JankStatsAggregator ীࢲ ా೤ ੿ࠁ ઁҕ
  39. API ۨ߰ 16ө૑ ഐജ оמ ղࠗ ോܻझ౮ਸ ࢎਊೞৈ ࢿמ ޙઁ

    ध߹ ࢎਊ੗ ࢚క ߂ ੘সী ؀ೠ ࣘࢿ ؘ੉ఠী UI ஶఫझ౟ ઁҕ ܻझցܳ ా೧ ݽٚ ೐ۨ੐ী ؀ೠ Ѿҗ ࠁҊ JankStats https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  40. Tracing stable androidx.tracing:tracing:1.1.0 System trace bufferী trace event ӝ۾ ٣ߡӒо

    ইצ ࠽٘ীࢲ ੿ഛೠ ੉߮౟ ୶੸ https://www.youtube.com/watch?v=jTd82lcuHTU IO 22 What’s new in Jetpack
  41. import androidx.tracing.trace; fun loadIcon() = trace(“Loading Icon”) { //... }

    https://www.youtube.com/watch?v=0adLO2VRJtc IO 21 Macrobenchmark۽ ߡߢѢܿ ߂ झఋ౟স ஏ੿
  42. Thank you! IO 22 What’s new in Jetpack IO 22

    What’s new in App Performanc e IO 21 Measuring Jank and Startup with Macrobenchmark Resources veronikapj GDG Korea Android PilJu BAE developer.android.com