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.

Kotlin

benchmarkRule.measureRepeated(
    packageName = TARGET_PACKAGE,
    metrics = listOf(
        FrameTimingMetric(),
        TraceSectionMetric("RV CreateView"),
        TraceSectionMetric("RV OnBindView"),
    ),
    iterations = 5,
    // ...
)

Java

benchmarkRule.measureRepeated(
    TARGET_PACKAGE,     // packageName
    Arrays.asList(      // metrics
        new StartupTimingMetric(),
        new TraceSectionMetric("RV CreateView"),
        new TraceSectionMetric("RV OnBindView"),
    ),
    5,                  // Iterations
    // ...
);

Dalam contoh ini, RV CreateView dan RV OnBindView adalah ID blok yang dapat dilacak dan ditentukan dalam RecyclerView. Kode sumber untuk metode createViewHolder() adalah contoh cara menentukan blok yang dapat dilacak dalam kode Anda sendiri.

StartupTimingMetric, TraceSectionMetric, FrameTimingMetric, dan PowerMetric akan dibahas secara mendetail nanti dalam dokumen ini.

Hasil benchmark adalah output ke Android Studio, seperti ditunjukkan pada Gambar 1. Jika beberapa metrik ditentukan, semuanya digabungkan dalam output.

Hasil TraceSectionMetric dan FrameTimingMetric
Gambar 1. Hasil TraceSectionMetric dan FrameTimingMetric.

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 Activity tujuan.
  • timeToFullDisplayMs: Jumlah waktu sejak sistem menerima intent peluncuran hingga saat laporan aplikasi sepenuhnya digambar menggunakan metode reportFullyDrawn(). Pengukuran berhenti saat rendering frame pertama selesai setelah, atau berisi, panggilan reportFullyDrawn(). Pengukuran ini mungkin tidak tersedia di Android 10 (level API 29) dan yang lebih rendah.

StartupTimingMetric menghasilkan nilai minimal, median, dan maksimum dari iterasi startup. Untuk menilai peningkatan startup, Anda harus berfokus pada nilai median, karena nilai median memberikan perkiraan terbaik dari waktu startup biasa. Untuk mengetahui informasi selengkapnya tentang faktor yang memengaruhi waktu startup aplikasi, lihat Waktu startup aplikasi.

Hasil StartupTimingMetric
Gambar 2. Hasil StartupTimingMetric.

Meningkatkan akurasi pengaturan waktu startup

Dua metrik utama untuk mengukur waktu startup aplikasi adalah waktu hingga tampilan awal (TTID) dan waktu hingga tampilan penuh (TTFD). TTID adalah waktu yang diperlukan untuk menampilkan frame pertama UI aplikasi. TTFD juga mencakup waktu untuk menampilkan konten apa pun yang dimuat secara asinkron setelah frame awal ditampilkan.

TTFD dilaporkan setelah metode reportFullyDrawn() dari ComponentActivity dipanggil. Jika reportFullyDrawn() tidak pernah dipanggil, TTID akan dilaporkan. Anda mungkin harus menunda saat reportFullyDrawn() dipanggil hingga pemuatan asinkron selesai. Misalnya, jika UI berisi daftar dinamis, seperti RecyclerView atau daftar lambat, UI ini mungkin diisi oleh tugas latar belakang yang selesai setelah daftar pertama kali digambar dan, karenanya, setelah UI ditandai sebagai digambar sepenuhnya. Dalam kasus tersebut, pengisian daftar tidak disertakan dalam tolok ukur.

Untuk menyertakan pengisian daftar sebagai bagian dari waktu benchmark, dapatkan FullyDrawnReporter dengan menggunakan getFullyDrawnReporter(), dan tambahkan pelapor ke dalamnya pada kode aplikasi Anda. Anda harus melepaskan pelapor setelah tugas latar belakang selesai mengisi daftar.

FullyDrawnReporter tidak memanggil metode reportFullyDrawn() hingga semua pelapor tambahan dilepaskan. Dengan menambahkan pelapor hingga proses latar belakang selesai, pengaturan waktu juga menyertakan jumlah waktu yang diperlukan untuk mengisi daftar dalam data waktu startup. Tindakan ini tidak mengubah perilaku aplikasi untuk pengguna, tetapi memungkinkan data startup pengaturan waktu menyertakan waktu yang diperlukan untuk mengisi daftar.

Contoh berikut menunjukkan cara menjalankan beberapa tugas latar belakang secara serentak, dengan mendaftarkan pelapor masing-masing:

Kotlin

class MainActivity : ComponentActivity() {

    sealed interface ActivityState {
        data object LOADING : ActivityState
        data object LOADED : ActivityState
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            var activityState by remember {
                mutableStateOf(ActivityState.LOADING as ActivityState)
            }
            fullyDrawnReporter.addOnReportDrawnListener {
                activityState = ActivityState.LOADED
            }
            ReportFullyDrawnTheme {
                when(activityState) {
                    is ActivityState.LOADING -> {
                        // Display the loading UI.
                    }
                    is ActivityState.LOADED -> {
                        // Display the full UI.
                    }
                }
            }
            SideEffect {
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
            }
        }
    }
}

Java

public class MainActivity extends ComponentActivity {
    private FullyDrawnReporter fullyDrawnReporter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        fullyDrawnReporter = getFullyDrawnReporter();
        fullyDrawnReporter.addOnReportDrawnListener(() -> {
            // Trigger the UI update.
            return Unit.INSTANCE;
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

               fullyDrawnReporter.removeReporter();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

                fullyDrawnReporter.removeReporter();
            }
        }).start();
    }
}

reportFullyDrawn() tidak dipanggil sampai semua tugas selesai, terlepas dari urutannya.

Jika aplikasi menggunakan Jetpack Compose, Anda dapat menggunakan API berikut untuk menunjukkan status yang digambar sepenuhnya:

  • ReportDrawn: menunjukkan bahwa composable Anda langsung siap untuk berinteraksi.
  • ReportDrawnWhen: mengambil predikat, seperti list.count > 0, untuk menunjukkan kapan composable siap berinteraksi.
  • ReportDrawnAfter: mengambil metode penangguhan yang, setelah selesai, menunjukkan bahwa composable Anda siap untuk berinteraksi.

FrameTimingMetric

FrameTimingMetric menangkap informasi pengaturan waktu dari frame yang dihasilkan oleh benchmark, seperti scrolling atau animasi dan menghasilkan nilai berikut:

  • frameOverrunMs: jumlah waktu ketika frame tertentu melewati batas waktu. Angka positif menunjukkan penurunan frame dan jank atau ketersendatan yang terlihat. Angka negatif menunjukkan seberapa cepat frame dibandingkan dengan batas waktu. Catatan: Ini hanya tersedia di Android 12 (level API 31) dan yang lebih baru.
  • frameDurationCpuMs: Jumlah waktu yang dibutuhkan frame untuk dihasilkan di CPU pada UI thread dan RenderThread.

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

Untuk informasi selengkapnya tentang cara mengidentifikasi dan meningkatkan frame lambat, lihat Rendering lambat.

Hasil FrameTimingMetric
Gambar 3. Hasil FrameTimingMetric.

TraceSectionMetric

TraceSectionMetric mencatat berapa kali kemunculan bagian rekaman aktivitas yang cocok dengan sectionName yang diberikan dan jumlah waktu yang diperlukan. Untuk waktunya, class ini menghasilkan waktu minimum, median, dan maksimum dalam milidetik. Bagian rekaman aktivitas ditentukan oleh panggilan fungsi trace(sectionName) atau kode antara Trace.beginSection(sectionName) dan Trace.endSection() atau varian asinkronnya. Class ini selalu memilih instance pertama dari bagian rekaman aktivitas yang diambil selama pengukuran. Class ini hanya menghasilkan bagian rekaman aktivitas dari paket secara default. Untuk menyertakan proses di luar paket Anda, setel targetPackageOnly = false.

Untuk mengetahui informasi selengkapnya tentang rekaman aktivitas, lihat Ringkasan pelacakan sistem dan Menentukan peristiwa kustom.

TraceSectionMetric
Gambar 4. Hasil TraceSectionMetric.

PowerMetric

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

Metrik ini mengukur konsumsi seluruh sistem, bukan konsumsi per aplikasi, dan terbatas untuk perangkat Pixel 6, Pixel 6 Pro, dan yang lebih baru:

  • power<category>Uw: jumlah daya yang dikonsumsi selama durasi pengujian dalam kategori ini.
  • energy<category>Uws: jumlah energi yang ditransfer per unit waktu selama durasi pengujian dalam kategori ini.

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.

Hasil PowerMetric
Gambar 5. Hasil PowerMetric.