Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
How to use Macrobenchmark
Search
Veronikapj
July 20, 2024
Programming
0
290
How to use Macrobenchmark
Google I/O extended Android Korea 2024 에서 벤치마크 사용 설명서란 주제로 발표한 내용입니다.
https://festa.io/events/5509
Veronikapj
July 20, 2024
Tweet
Share
More Decks by Veronikapj
See All by Veronikapj
The Know-how of Seniors in the Age of AI
veronikapj
0
36
Gemini in Android Studio I/O extended 2024
veronikapj
0
340
앱 성능 영혼까지 끌어올리기
veronikapj
0
970
Software Productivity - Devfest Songdo 2023
veronikapj
0
970
파이어베이스로 서비스 품질 올리기
veronikapj
0
320
What's new in Android IO23 Daejeon
veronikapj
1
270
KC23_Coroutine_Testing
veronikapj
0
150
ComposeCamp2022 Pathway2
veronikapj
1
380
io22 extended What's new in app performance
veronikapj
0
990
Other Decks in Programming
See All in Programming
なぜイベント駆動が必要なのか - CQRS/ESで解く複雑系システムの課題 -
j5ik2o
11
3.9k
2024年のWebフロントエンドのふりかえりと2025年
sakito
3
250
仕様変更に耐えるための"今の"DRY原則を考える / Rethinking the "Don't repeat yourself" for resilience to specification changes
mkmk884
0
320
個人アプリを2年ぶりにアプデしたから褒めて / I just updated my personal app, praise me!
lovee
0
350
JavaScriptツール群「UnJS」を5分で一気に駆け巡る!
k1tikurisu
9
1.8k
Honoとフロントエンドの 型安全性について
yodaka
7
1.3k
Pythonでもちょっとリッチな見た目のアプリを設計してみる
ueponx
1
570
GAEログのコスト削減
mot_techtalk
0
120
Spring gRPC について / About Spring gRPC
mackey0225
0
220
GitHub Actions × RAGでコードレビューの検証の結果
sho_000
0
270
Amazon ECS とマイクロサービスから考えるシステム構成
hiyanger
2
560
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
210
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
336
57k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
Typedesign – Prime Four
hannesfritz
40
2.5k
Designing Experiences People Love
moore
140
23k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
The World Runs on Bad Software
bkeepers
PRO
67
11k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
GitHub's CSS Performance
jonrohan
1030
460k
Transcript
# Performance Macrobenchmark ࢎਊ ࢸݺࢲ ߓ | GDG Korea Android
ஏਸ ా೧ ୡӝ ࢿמਸ ࢸפ. ޙઁܳ ੌਵఃח ਗੋਸ ഛੋפ. ஏೞӝ
ਗੋ ঈ ࢿמ ޙઁܳ ೧Ѿೞח ߑߨ ഛੋೠ ղਊী ٮۄ ٘ܳ ࣻפ. ٘ ࣻ ࢿמਸ ஏೞҊ ୡӝ ࢿמҗ ࠺Үפ. ୡӝ ࢿמҗ ࠺Ү 🙆 Intro
Intro ٘ী ऀযח Unstable Parameters ܳ ݽف ୶ೞҊ ࣻೞ ݃ࣁਃ.
🙅 хਵ۽ ନ ݈ӝ! ೧ ஹನ࠶ ܻஹನ࣌ਸ ਬߊೞח গפݫ࣌ਸ ઁೞ݃ࣁਃ. хী ٮۄ ੍ӝ য۰ ୭ചܳ प೯ೞ ݃ࣁਃ.
ஏਸ ా೧ ୡӝ ࢿמਸ ࢸפ. ޙઁܳ ੌਵఃח ਗੋਸ ഛੋפ. ஏೞӝ
ਗੋ ঈ ࢿמ ޙઁܳ ೧Ѿೞח ߑߨ Intro ഛੋೠ ղਊী ٮۄ ٘ܳ ࣻפ. ٘ ࣻ ࢿמਸ ஏೞҊ ୡӝ ࢿמҗ ࠺Үפ. ୡӝ ࢿמҗ ࠺Ү
ࢿמ ޙઁܳ ખ ؊ औѱ ӝ ਤೠ ஏী ೠ ঠӝ
݃ߨ ইתפ. 🧙 # Performance
Intro জ ղࠗ ز ঌ ਃ হ UiAutomatorܳ ࢎ ਊ೧ࢲ
ࢿמਸ ஏפ. Jetpack Macrobenchmark ਬо ࠁח Ѫҗ э ࢿמਸ ഛੋפ. Performance ബҗ ஏਸ ਤೠ ୶ୌೞח ߑߨ ࢿמ ஏ पઁ ࢎਊ ജ҃ ࢿמ CIীࢲ प೯ ଵҊ : పझী ೠ ӝࠄੋ ೧
ޖਸ ஏ ೡ ࣻ աਃ? Intro জ दೡ ٸ৬
۽٘ ؼ ٸ ݃ա Ѧܻח Startup Timing 01 Frame Timing 02 Frameਸ ࢤࢿೞחؘ ݃ա Ѧܻח Trace Section 03 নೠ ஏਸ ೧ࠅ ࣻ ח ਊب API Memory Usage 04 জ ݃ա ݆ ݫݽܻܳ ࢎਊೞҊ ח Power 05 জ ݃ա ݆ ߓఠܻܳ ࣗݽೞҊ ח + https://developer.android.com/topic/performance/benchmarking/macrobenchmark-metrics
https://developer.android.com/codelabs/jetpack-compose-performance#0 Practical performance problem solving in Jetpack Compose ஏೞӝ
ஏೞӝ Macrobenchmark ݽٕ Macrobenchmarkח জ ٘৬ ܻ࠙ غয জ ஏ
పझ प೯ਸ ೞח com.android.test ݽٕ ਃפ.
ޖѢ Composable ୭ച ೞӝ ஏೞӝ
ஏೞӝ ஏ ҅ദ ࣁӝ • Layout Inspectorܳ ࢎਊ೧ࢲ ҳઑܳ ঈ
• п Layout ߹ दрਸ ஏ
ஏೞӝ Layout ҳઑ • Column : HeavyItem • PublishedText •
PublishDate.format • Layout : ImageDisplay • ImagePlaceHolder • ItemTag
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } }
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() fun benchmark(compilationMode: CompilationMode) { } } class MacrobenchmarkRule : TestRule JUnit ӏਸ ࢎਊೞৈ গܻா࣌ द, झ܀݂ ژח গפݫ࣌җ э ӏݽ সਸ ߮݃ఊೞח ߑߨਸ ઁҕפ. https://developer.android.com/reference/kotlin/androidx/benchmark/macro/junit4/MacrobenchmarkRule
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } }
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @Test fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) }
https://developer.android.com/reference/androidx/benchmark/macro/CompilationMode CompilationMode.Partial জ द ࢿמ ஏೞҊ ೧ೞחؘ ࢎਊ (Default) CompilationMode.Full জ प೯ runtime ࢿמ ࠺Ү ߂ ѐࢶ JIT ୭ച۽ ੋೠ ࢿמ ߸ز ਃੋ ઁѢ CompilationMode.None ࢎ ஹੌ হ. Baseline Pro fi le җ Benchmark ղীࢲ ࠺Ү CompilationMode
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } }
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( .
. . startupMode = StartupMode.WARM, } Sta rt upMode https://developer.android.com/topic/performance/benchmarking/macrobenchmark-metrics StartupMode.COLD Sta rt up Benchmarkী ࢎਊ setupBlock৬ mesureBlock ࢎী জ ۽ࣁझ ઙܐ StartupMode.WARM Frame timing Benchmarkী ࢎਊ setupBlock റী ۽ࣁझо ઙܐغ ঋ ۽ࣁझܳ ઙܐೞ ঋҊ ݽٚ प೯ ੋ Activityܳ ײ Activity द ߑधҗ పझ द द ۽ࣁझ ࢚క ߸҃ StartupMode.HOT п Activity ߹ நय ݫழפ્ਸ ஏೞחؘ ࢎਊ ۽ࣁझ, ী प೯ ؍ Activityب द غ ঋ Null Macrobenchmark о ইޖѪب ೞ ঋח ݽ٘ killProcess() ۽ ஶ܀
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } } SetupBlock ਗೞח ஏ ചݶ Frame ө ز (۽Ӓੋ ١)
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } } MeasureBlock ஏਸ ਗೞח ز
MeasureBlock ஏਸ ਗೞח ز override fun MacrobenchmarkScope.measureBlock() { pressHome() startTaskActivity("accelerate_heavy")
device.wait( Until.hasObject(By.res("list_of_items")), 5_000) val feed = device.findObject(By.res("list_of_items")) feed.setGestureMargin(device.displayWidth / 5) repeat(2) { feed.drag( Point( feed.visibleCenter.x, feed.visibleBounds.top ) ) Thread.sleep(500) } }
MeasureBlock TestTagܳ ࠢৈࢲ ਗೞח resource ইоӝ @Composable fun ScreenContent(items: List<HeavyItem>)
{ LazyVerticalGrid( modifier = Modifier .fillMaxSize() .testTag(“list_of_items"), . . . ) { items(items) { item -> HeavyItem(item) } } } device.wait(Until.hasObject(By.res("list_of_items")), 5_000)
MeasureBlock TestTagܳ ࠢৈࢲ ਗೞח resource ইоӝ @Composable fun ScreenContent(items: List<HeavyItem>)
{ LazyVerticalGrid( modifier = Modifier .fillMaxSize() .testTag(“list_of_items"), . . . ) { items(items) { item -> HeavyItem(item) } } } device.wait(Until.hasObject(By.res("list_of_items")), 5_000)
MeasureBlock ஏਸ ਗೞח ز - झ܀ override fun MacrobenchmarkScope.measureBlock() {
pressHome() startTaskActivity("accelerate_heavy") device.wait( Until.hasObject(By.res("list_of_items")), 5_000) val feed = device.findObject(By.res("list_of_items")) feed.setGestureMargin(device.displayWidth / 5) repeat(2) { feed.drag( Point( feed.visibleCenter.x, feed.visibleBounds.top ) ) Thread.sleep(500) } }
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test
fun accelerateHeavyScreenCompilation() = benchmark(CompilationMode.Partial()) fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( packageName = "com.compose.performance", metrics = listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum) ), compilationMode = compilationMode, startupMode = StartupMode.WARM, iterations = 10, setupBlock = { setupBlock() }, measureBlock = { measureBlock() } ) } } ஏ ೦ݾ https://developer.android.com/topic/performance/benchmarking/macrobenchmark-metrics
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( .
. . metrics = listOf( FrameTimingMetric() . . .), } frameDurationCpuMs P50 11.9, P90 24.0, P95 30.3, P99 90.6 frameOverrunMs P50 3.5, P90 21.2, P95 25.9, P99 252.0 FrameTimingMetric 👉 CPUীࢲ UI झۨ٘৬ RenterThreadীࢲ ۨ ࢤࢿغחؘ Ѧܽ दр https://developer.android.com/topic/performance/benchmarking/macrobenchmark-metrics
@RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( .
. . metrics = listOf( FrameTimingMetric() . . .), } frameDurationCpuMs P50 11.9, P90 24.0, P95 30.3, P99 90.6 frameOverrunMs P50 3.5, P90 21.2, P95 25.9, P99 252.0 FrameTimingMetric 👉 CPUীࢲ UI झۨ٘৬ RenterThreadীࢲ ۨ ࢤࢿغחؘ Ѧܽ दр 👉 য ۨ ӝೠਸ ֈӟ दр +(নࣻ)ੌ ࣻ۾ ߡߢѢܿ, - (ࣻ)ח ݃ա ࡅܲ Android 12(API 31) https://developer.android.com/topic/performance/benchmarking/macrobenchmark-metrics
ஏೞӝ TraceSection Metric • Column : HeavyItem • PublishedText •
PublishDate.format • Layout : ImageDisplay • ImagePlaceHolder • ItemTag Layout ҳઑ ߹۽ ࢸ
listOf( FrameTimingMetric(), TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum), TraceSectionMetric("PublishedText", TraceSectionMetric.Mode.Sum), TraceSectionMetric("PublishDate.format", TraceSectionMetric.Mode.Sum), TraceSectionMetric("ImageDisplay", TraceSectionMetric.Mode.Sum),
TraceSectionMetric("ImagePlaceholder", TraceSectionMetric.Mode.Sum), TraceSectionMetric("ItemTag", TraceSectionMetric.Mode.Sum) ) @RunWith(AndroidJUnit4::class) class HeavyScreenBenchmark { fun benchmark(compilationMode: CompilationMode) { rule.measureRepeated( . . . metrics = listOf(FrameTimingMetric(). . .), } TraceSectionMetric Trace Section ઁҕػ sectionName җ ੌೞח പࣻ৬ ࣗਃػ दр ୭ࣗदр, ঔ ч, ୭ दр (ms) h tt ps://developer.android.com/topic/pe rf ormance/benchmarking/macrobenchmark-metrics?hl=ko#trace-section
TraceSectionMetric.Mode TraceSectionMetric("HeavyItem", TraceSectionMetric.Mode.Sum), https://developer.android.com/reference/androidx/benchmark/macro/TraceSectionMetric.Mode Mode.First SectionName ੌೞח ߣ૩ ࣂ࣌ instance
ࣗਃदр Mode.Sum SectionName ੌೞח ݽٚ ࣂ࣌ instance ࣗਃ दр ҅ Mode.Max SectionName ੌೞח ࣂ࣌ о ч ӝ۾ Mode.Min SectionName ੌೞח ࣂ࣌ о ч ӝ۾ Mode.Average SectionName ੌೞח ࣂ࣌ ಣӐ Mode.Count SectionName ੌೞח ࣂ࣌ ѐࣻ 1.3.0 beta+ 1.3.0 beta+ 1.3.0 beta+ 1.3.0 beta+
ஏೞӝ _count : SectionName җ ੌೞח іࣻ _ms : Section
ஏػ ࣗਃ दр TraceSectionMetric ஏ Ѿҗ
ஏೞӝ HeavyItem PublishedText PublishDate.format ImageDisplay ImagePlaceHolder ItemTag Min Median Max
HeavyItem 46.4 50.2 53.0 PublishedText 6.9 7.7 8.6 PublishDate.format 0.7 0.8 0.9 ImageDisplay 27.1 29.1 30.4 ImagePlaceHolder 17.4 18.6 19.3 ItemTag 2.7 3.6 5.4 TraceSectionMetric ஏ Ѿҗ
System Trace ࠁ۞оӝ ਗੋঈ Test Resultsীࢲ Ѿҗ link ࠗ࠙ ܼ
Trace ੌ ਤ Measure > build > outputs > connected_android_text_additional_output
> benchmarkRelease > connected > ‘connected device’ ਗੋঈ
ਗੋঈ Pro fi ler System Trace
উ٘۽٘ झౚ٣য় प೯ ਃ হ ٣߄झ Threadܳ ࠅ ࣻ
Trace , प೯غח SQL quries ਗੋঈ Web-based tool Gives you whole picture https://youtu.be/Z96wfbID_Yc?si=pOe8w7hT7IEbsnb-&t=655 Investigate deeper H tt ps://ui.pe rf e tt o.dev/
ਗੋঈ Pe rf e tt o
ਗੋঈ Expected Timeline दझమীࢲ ۨ ࢤࢿೞח ࢚ ఋۄੋ
ਗੋঈ Actual Timeline ࢚ࠁ য়ې Ѧ۰ࢲ ࢤࢿػ ۨ पઁ۽ ۨ
ࢤࢿػ दр
ਗੋঈ System-tracing call cha r दр ইې ഐػ ೣࣻ
ࣗਃ दр ୨ Trace Code Untrace Code
ਗੋঈ о য়ې Ѧܻח স ࠙ࢳೞӝ HeavyItem ࣗਃ दр
ਗੋঈ о ݆ ରೞח दр ImageDisplay о য়ې Ѧܻח স
࠙ࢳೞӝ
ਗੋঈ Image ۽٘ೞחؘ Placeholder о о য়ې Ѧܻ֎?? о য়ې
Ѧܻח স ࠙ࢳೞӝ
ਗੋঈ https://developer.android.com/develop/ui/compose/tooling/tracing दػ ݅ ୶ য়ߡ٘о Ҋ জ ࢿמী
ೱਸ ঋ জ ݽٚ ೣࣻ ഐਸ ୶ জ ࢿמী ೱਸ ݅ ߊࢤೞ ח ࢚ട, ഐغח ೣࣻ, ഐ ࠼بܳ ਵ۽ ঈ Composition function ನೣغয ঋ Composition function ನೣ Composition Tracing +
// :app module implementation( “androidx.compose.runtime:runtime-tracing:1.0.0-beta01" ) https://developer.android.com/develop/ui/compose/tooling/tracing // :mesure module
implementation( “androidx.tracing:tracing-perfetto:1.0.0") implementation( "androidx.tracing:tracing-perfetto-binary:1.0.0") // gradle configuration androidx.benchmark.fullTracing.enable=true
ਗੋঈ Composition function ҙ оמ
ImagePlaceHolder ѐࢶ 1. ܳ ࠺زӝ۽ ۽٘ 2. ؊ ࡈܻ ۽٘غب۾
ࢎਊ 3. ਃೠ ӝী ٮۄ ઑغח Vector Drawable ࢎਊ ٘ࣻ
1600 x 1600 px @Composable fun imagePlaceholder() = trace("ImagePlaceholder") {
painterResource(R.drawable.placeholder) } ٘ࣻ
@Composable fun imagePlaceholder() = trace("ImagePlaceholder") { painterResource(R.drawable.placeholder_vector) } placeholder_vector.xml ٘ࣻ
TraceSectionMetric ஏ Ѿҗ ୡӝ ࢿמҗ ࠺Ү
ѐࢶ Ѿҗ Before A ft er Max ӝળ 19.3 ীࢲ
4.4 ۽ 77.2% хࣗ ୡӝ ࢿמҗ ࠺Ү
Before A ft er ୡӝ ࢿמҗ ࠺Ү
ஏਸ ా೧ ୡӝ ࢿמਸ ࢸפ. ޙઁܳ ੌਵఃח ਗੋਸ ഛੋפ. ஏೞӝ
ਗੋ ঈ ࢿמ ޙઁܳ ೧Ѿೞח ߑߨ ഛੋೠ ղਊী ٮۄ ٘ܳ ࣻפ. ٘ ࣻ ࢿמਸ ஏೞҊ ୡӝ ࢿמҗ ࠺Үפ. ୡӝ ࢿמҗ ࠺Ү 🙆 Intro
ஏਸ ా೧ ୡӝ ࢿמਸ ࢸפ. ޙઁܳ ੌਵఃח ਗੋਸ ഛੋפ. ஏೞӝ
ਗੋ ঈ ഛੋೠ ղਊী ٮۄ ٘ܳ ࣻפ. ٘ ࣻ ࢿמਸ ஏೞҊ ୡӝ ࢿמҗ ࠺Үפ. ୡӝ ࢿמҗ ࠺Ү ܻ Macrobenchmark ࢸೞӝ ஏ чٜ ঌইࠁӝ Ѿҗ ч ࠺Үೞӝ Profiler ژח Perfetto chart ೧ೞӝ ޖѢ স оߺѱ ѐࢶೞӝ ࣻ റ ബҗо ח ࠺Үೞӝ
хࢎפ. ߓ veronikapj GDG Korea Android Resources https://developer.android.com/codelabs/jetpack-compose-performance