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 merepresentasikan bagian rekaman aktivitas kustom yang ditentukan di dalam lapisan item composable menggunakan wrapper blok trace(sectionName) { ... } Kotlin standar. Untuk menyediakan data bagi TraceSectionMetric, Anda harus membungkus komponen UI target di dalam codebase produksi aplikasi dengan wrapper blok runtime Jetpack standar trace:

@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 langsung ditampilkan ke tab terminal Benchmark di dalam Android Studio, seperti yang ditunjukkan pada Gambar 1. Jika beberapa metrik ditentukan, semua titik data yang dihitung digabungkan dalam 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 dalam 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 aplikasi melaporkan sepenuhnya digambar menggunakan mekanisme pelaporan platform internal. Pengukuran berhenti saat rendering frame pertama selesai setelah—atau berisi—sinyal digambar sepenuhnya.

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

Dalam arsitektur yang mengutamakan Compose, 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 Anda untuk otomatis memberi sinyal ke Macrobenchmark saat data jaringan asinkron atau status UI kompleks Anda 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 jank atau ketersendatan yang terlihat. Angka negatif menunjukkan seberapa cepat penyelesaian frame 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 digunakan frame untuk diproduksi secara aktif di CPU di seluruh 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 berat.

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

TraceSectionMetric

TraceSectionMetric mencatat berapa kali kemunculan bagian rekaman aktivitas tertentu dan jumlah waktu absolut yang diperlukan untuk dieksekusi. 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 yang 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 fungsi composable individual dalam grafik rekaman aktivitas sistem tanpa menulis wrapper rekaman aktivitas manual dengan mengaktifkan pelacakan komposisi.

Meskipun menambahkan dependensi androidx.compose.runtime:runtime-tracing ke aplikasi target sudah cukup untuk rekaman aktivitas profiler manual, pengambilan rekaman aktivitas ini secara terprogram dalam eksekusi Macrobenchmark memerlukan konfigurasi tambahan di dalam modul benchmark.

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

PowerMetric

PowerMetric merekam perubahan daya atau energi selama durasi jalannya Macrobenchmark Anda. Setiap kategori yang dipilih dibagi menjadi komponen hardware yang dapat diukur, 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 terbatas pada 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.
  • 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 jalur hardware selama pengujian, kunci kecerahan layar ke nilai tetap, jaga suhu perangkat tetap stabil, dan tutup proses latar belakang yang bersaing sebelum memulai loop Macrobenchmark.

Referensi lainnya

Melihat konten