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
340
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
Google I/O 요약만 봤다고? AI가 못 보는 진짜 이야기
veronikapj
0
53
The Know-how of Seniors in the Age of AI
veronikapj
0
69
Gemini in Android Studio I/O extended 2024
veronikapj
0
390
앱 성능 영혼까지 끌어올리기
veronikapj
0
1.1k
Software Productivity - Devfest Songdo 2023
veronikapj
0
1k
파이어베이스로 서비스 품질 올리기
veronikapj
0
360
What's new in Android IO23 Daejeon
veronikapj
1
290
KC23_Coroutine_Testing
veronikapj
0
160
ComposeCamp2022 Pathway2
veronikapj
1
400
Other Decks in Programming
See All in Programming
プロパティベーステストによるUIテスト: LLMによるプロパティ定義生成でエッジケースを捉える
tetta_pdnt
0
4.3k
デザイナーが Androidエンジニアに 挑戦してみた
874wokiite
0
550
旅行プランAIエージェント開発の裏側
ippo012
2
930
Azure SRE Agentで運用は楽になるのか?
kkamegawa
0
2.5k
Testing Trophyは叫ばない
toms74209200
0
890
Platformに“ちょうどいい”責務ってどこ? 関心の熱さにあわせて考える、責務分担のプラクティス
estie
1
120
テストコードはもう書かない:JetBrains AI Assistantに委ねる非同期処理のテスト自動設計・生成
makun
0
540
🔨 小さなビルドシステムを作る
momeemt
4
690
為你自己學 Python - 冷知識篇
eddie
1
350
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
420
@Environment(\.keyPath)那么好我不允许你们不知道! / atEnvironment keyPath is so good and you should know it!
lovee
0
130
複雑なドメインに挑む.pdf
yukisakai1225
5
1.2k
Featured
See All Featured
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
131
19k
Faster Mobile Websites
deanohume
309
31k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
580
Building Adaptive Systems
keathley
43
2.7k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
127
53k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
How to train your dragon (web standard)
notwaldorf
96
6.2k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Done Done
chrislema
185
16k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
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