Mengambil metrik Macrobenchmark

Metrik adalah jenis informasi utama yang diekstrak dari benchmark Anda. Metrik diteruskan ke fungsi measureRepeated sebagai List, yang memungkinkan Anda menentukan beberapa metrik terukur sekaligus. Setidaknya satu jenis metrik diperlukan agar benchmark dapat dijalankan.

Cuplikan kode berikut menangkap waktu render frame dan metrik bagian rekaman aktivitas kustom untuk antarmuka tata letak lambat Jetpack Compose:

@OptIn(ExperimentalMetricApi::class)
    @Test
    fun scrollComposeList() {
        benchmarkRule.measureRepeated(
            // [START_EXCLUDE]
            packageName = TARGET_PACKAGE,
            metrics = listOf(
                FrameTimingMetric(),
                // Measure power usage. This is supported on Pixel 6 and later.
                PowerMetric(PowerMetric.Type.Power(
                    mapOf(
                        PowerCategory.CPU to PowerCategoryDisplayLevel.TOTAL,
                        PowerCategory.DISPLAY to PowerCategoryDisplayLevel.TOTAL,
                        PowerCategory.GPU to PowerCategoryDisplayLevel.TOTAL,
                        PowerCategory.NETWORK to PowerCategoryDisplayLevel.TOTAL,
                    )
                )),
                // Measure custom trace sections by name EntryRow (which is added to the EntryRow composable).
                // Mode.Sum measures combined duration and also how many times it occurred in the trace.
                // This way, you can estimate whether a composable recomposes more than it should.
                TraceSectionMetric("EntryRowCustomTrace", TraceSectionMetric.Mode.Sum),
                // This trace section takes into account the SQL wildcard character %,
                // which can find trace sections without the full name.
                // This way, you can measure composables produced by the composition tracing
                // and measure how long they took and how many times they recomposed.
                // WARNING: This metric only shows results when running with composition tracing, otherwise it won't be visible in the outputs.
                TraceSectionMetric("%EntryRow%", TraceSectionMetric.Mode.Sum),
            ),
            // Try switching to different compilation modes to see the effect
            // it has on frame timing metrics.
            compilationMode = CompilationMode.None(),
            startupMode = StartupMode.WARM, // restarts activity each iteration
            iterations = DEFAULT_ITERATIONS,
            // [END_EXCLUDE]
            setupBlock = {
                uiAutomator {
                    // Before starting to measure, navigate to the UI to be measured.
                    startIntent(Intent("$packageName.COMPOSE_ACTIVITY"))
                }
            }
        ) {
            uiAutomator {
                onElement { isScrollable }.fling(Direction.DOWN)
            }
        }
    }

Dalam contoh berikut, EntryRowCustomTrace mewakili bagian trace kustom yang ditentukan di dalam lapisan item composable menggunakan wrapper blok trace(sectionName) { ... } Kotlin standar. Untuk menyediakan data bagi TraceSectionMetric, Anda harus menggabungkan komponen UI target di dalam codebase produksi aplikasi dengan wrapper blok trace runtime Jetpack standar:

@Composable
private fun EntryRow(entry: Entry, modifier: Modifier = Modifier) = trace("EntryRowCustomTrace") {
    Card(modifier = modifier) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            Text(
                text = entry.contents,
                modifier = Modifier
                    .padding(16.dp)
                    .wrapContentSize()
            )

            Spacer(modifier = Modifier.weight(1f))

            Checkbox(
                checked = false,
                onCheckedChange = {},
                modifier = Modifier.padding(16.dp)
            )
        }
    }
}

Hasil benchmark adalah output langsung ke tab terminal Benchmark di dalam Android Studio, seperti yang ditunjukkan pada Gambar 1. Jika beberapa metrik ditentukan, semua titik data yang dihitung akan digabungkan di jendela ringkasan.

Hasil TraceSectionMetric dan FrameTimingMetric
Gambar 1. Hasil konsol gabungan TraceSectionMetric dan FrameTimingMetric untuk tata letak Compose modern.

StartupTimingMetric, FrameTimingMetric, TraceSectionMetric, dan PowerMetric dibahas secara mendetail di bawah. Untuk mengetahui daftar lengkap metrik tolok ukur yang tersedia, lihat subclass Metric di referensi API.

StartupTimingMetric

StartupTimingMetric mengambil metrik pengaturan waktu startup aplikasi dengan nilai berikut:

  • timeToInitialDisplayMs: Jumlah waktu sejak sistem menerima intent peluncuran hingga saat sistem merender frame pertama layar tujuan.
  • timeToFullDisplayMs: Jumlah waktu sejak sistem menerima intent peluncuran hingga saat laporan aplikasi sepenuhnya digambar menggunakan mekanisme pelaporan platform internal. Pengukuran berhenti saat rendering frame pertama selesai setelah, atau berisi, sinyal yang digambar sepenuhnya.

StartupTimingMetric menghasilkan nilai minimum, median, dan maksimum dari iterasi startup. Untuk menilai peningkatan startup, selalu fokus pada nilai median, karena nilai median memberikan perkiraan terbaik dari waktu startup pengguna biasa.

Dalam arsitektur Compose-first, jangan mencoba memanggil activity.reportFullyDrawn secara manual. Sebagai gantinya, gunakan utilitas asinkron yang aman untuk Compose, yaitu ReportDrawn, ReportDrawnWhen, atau ReportDrawnAfter di dalam composable layar untuk otomatis memberi sinyal ke Macrobenchmark saat data jaringan asinkron atau status UI yang kompleks telah selesai dirender.

Untuk mengetahui informasi selengkapnya tentang cara menganalisis dan mengoptimalkan performa inisialisasi, lihat Waktu startup aplikasi.

FrameTimingMetric

FrameTimingMetric menangkap informasi pengaturan waktu yang akurat dari frame yang dihasilkan oleh perjalanan benchmark, seperti men-scroll daftar atau animasi tata letak UI yang kompleks, dan menghasilkan nilai diagnostik berikut:

  • frameOverrunMs: jumlah waktu ketika frame tertentu melewati batas waktu. Angka positif menunjukkan penurunan frame yang disertai dengan jank atau kondisi tersendat yang terlihat. Angka negatif menunjukkan seberapa cepat frame selesai dibandingkan dengan batas waktu hardware subsistem. Catatan: Metrik ini hanya tersedia di Android 12 (level API 31) dan yang lebih baru.
  • frameDurationCpuMs: jumlah waktu yang dihabiskan frame untuk diproduksi secara aktif di CPU di UI thread aplikasi utama dan RenderThread Compose.

Pengukuran ini dikumpulkan dalam distribusi persentil ke-50, ke-90, ke-95, dan ke-99:

frameDurationCpuMs P50 3.5, P90 6.0, P95 6.4, P99 11.0
frameOverrunMs P50 -11.6, P90 -7.2, P95 -7.1, P99 -1.2

Saat mengoptimalkan hierarki tata letak Jetpack Compose, lihat frame dengan performa terburuk (batas P95 dan P99). Jika frameOverrunMs melonjak menjadi bilangan bulat positif pada persentil tinggi, hal ini menunjukkan bahwa rekomposisi menghambat thread utama selama animasi scroll yang berat.

Untuk mendapatkan insight yang lebih mendalam tentang cara mengidentifikasi dan menyelesaikan frame lambat, lihat Performa Jetpack Compose.

TraceSectionMetric

TraceSectionMetric mencatat berapa kali bagian rekaman aktivitas tertentu muncul dan jumlah waktu absolut yang diperlukan untuk mengeksekusinya. Untuk pelacakan waktu, class ini menghasilkan waktu minimum, median, dan maksimum dalam milidetik. Bagian rekaman aktivitas target ditentukan oleh panggilan fungsi trace(sectionName) atau batas blok tingkat lebih rendah antara Trace.beginSection(sectionName) dan Trace.endSection() atau varian asinkronnya.

EntryRowCustomTraceCount min 20.0, median 28.0, max 50.0
EntryRowCustomTraceSumMs min 34.9, median 44.4, max 66.6

Secara default, metrik hanya menghasilkan bagian rekaman aktivitas yang dikompilasi langsung dari biner paket aplikasi Anda sendiri. Untuk menyertakan proses yang berasal dari luar batas paket aplikasi Anda, tetapkan properti targetPackageOnly = false.

Saat mengerjakan Pelacakan Runtime Jetpack Compose, Anda dapat menampilkan setiap fungsi composable dalam grafik pelacakan sistem tanpa menulis wrapper pelacakan manual dengan mengaktifkan pelacakan komposisi.

Meskipun menambahkan dependensi androidx.compose.runtime:runtime-tracing ke aplikasi target sudah cukup untuk pelacakan profiler manual, menangkap pelacakan ini secara terprogram dalam operasi Macrobenchmark memerlukan konfigurasi tambahan di dalam modul benchmark Anda.

Untuk mengetahui petunjuk penyiapan lengkap, lihat Merekam aktivitas dengan Jetpack Macrobenchmark.

PowerMetric

PowerMetric merekam perubahan daya atau energi selama durasi eksekusi Macrobenchmark Anda. Setiap kategori yang dipilih dibagi menjadi komponen hardware terukur, sedangkan kategori yang tidak dipilih dikelompokkan ke dalam bucket "unselected".

Persyaratan Hardware: Metrik ini mengukur konsumsi seluruh sistem, bukan penghitungan per aplikasi. Oleh karena itu, pengumpulan data dibatasi untuk perangkat fisik Google Pixel 6, Pixel 6 Pro, dan perangkat fisik yang lebih baru.

Metrik ini menghasilkan dua pengukuran per kategori:

  • power<category>Uw: jumlah daya yang dikonsumsi selama durasi pengujian dalam kategori ini (diukur dalam mikrowatt).
  • energy<category>Uws: jumlah total energi yang ditransfer per unit waktu selama durasi pengujian dalam kategori ini (diukur dalam mikrowatt-detik).

Kategori mencakup:

  • CPU
  • DISPLAY
  • GPU
  • GPS
  • MEMORY
  • MACHINE_LEARNING
  • NETWORK
  • UNCATEGORIZED

Dengan beberapa kategori, seperti CPU, mungkin sulit untuk memisahkan pekerjaan yang dilakukan oleh proses lain dari pekerjaan yang dilakukan oleh aplikasi Anda sendiri. Untuk meminimalkan gangguan, hapus atau batasi aplikasi dan akun yang tidak diperlukan.

powerCategoryCpuUw min 300.2, median 346.1, max 519.6
powerCategoryDisplayUw min 319.8, median 325.8, max 329.7
powerCategoryGpuUw min 18.8, median 23.3, max 36.9
powerCategoryNetworkUw min 97.3, median 123.3, max 681.3
powerTotalUw min 1234.8, median 1316.6, max 2112.4
powerUnselectedUw       min  483.3,  median  512.6,  max  561.7

Menganalisis subsistem inti

PowerMetric merekam perubahan daya atau energi selama durasi pengujian untuk kategori daya yang disediakan. Setiap kategori yang Anda pilih dibagi menjadi subkomponen terukur, dan kategori yang tidak dipilih ditambahkan ke metrik "unselected".

Output terminal dipetakan ke konfigurasi yang Anda minta:

  • powerCategoryCpuUw: Jumlah daya yang dikonsumsi oleh CPU selama durasi pengujian.
  • powerCategoryGpuUw: Jumlah daya yang dikonsumsi oleh GPU selama durasi pengujian Anda.
  • powerUnselectedUw: Daya gabungan yang dikonsumsi oleh semua kategori hardware yang tersedia yang tidak diminta secara eksplisit dalam peta inisialisasi Anda.

Untuk mencegah lonjakan data yang tidak menentu pada rel hardware selama proses berjalan, kunci kecerahan layar ke nilai tetap, pertahankan suhu perangkat yang stabil, dan tutup proses latar belakang yang bersaing sebelum memulai loop Macrobenchmark.

Referensi lainnya

Konten penayangan