Meningkatkan performa aplikasi dengan Profil Dasar Pengukuran

1. Sebelum memulai

Codelab ini menunjukkan cara membuat Profil Dasar Pengukuran untuk mengoptimalkan performa aplikasi Anda dan cara memastikan manfaat pada performa saat menggunakan Profil Dasar Pengukuran.

Yang akan Anda butuhkan

Yang akan Anda lakukan

  • Menyiapkan project untuk menggunakan generator Profil Dasar Pengukuran.
  • Membuat Profil Dasar Pengukuran untuk mengoptimalkan startup aplikasi dan performa scroll.
  • Memverifikasi peningkatan performa dengan library Jetpack Macrobenchmark.

Yang akan Anda pelajari

  • Profil Dasar Pengukuran dan caranya meningkatkan performa aplikasi.
  • Cara membuat Profil Dasar Pengukuran.
  • Peningkatan performa dengan Profil Dasar Pengukuran.

2. Mempersiapkan

Untuk memulai, clone repositori GitHub dari command line dengan menggunakan perintah berikut:

$ git clone https://github.com/android/codelab-android-performance.git

Atau, Anda dapat mendownload dua file ZIP:

Membuka Project di Android Studio

  1. Di jendela Welcome to Android Studio, pilih 61d0a4432ef6d396.png Open an Existing Project.
  2. Pilih folder [Download Location]/codelab-android-performance/baseline-profiles. Pastikan Anda memilih direktori baseline-profiles.
  3. Saat Android Studio mengimpor project, pastikan Anda dapat menjalankan modul app untuk membangun aplikasi contoh yang akan Anda gunakan nanti.

Aplikasi contoh

Dalam codelab ini, Anda akan menggunakan aplikasi contoh JetSnack. Aplikasi ini adalah aplikasi pemesanan camilan virtual yang menggunakan Jetpack Compose.

Untuk mengukur performa aplikasi, Anda perlu memahami struktur UI dan perilaku aplikasi, sehingga Anda dapat mengakses elemen UI dari benchmark. Jalankan aplikasi dan pahami layar dasarnya dengan memesan camilan. Anda tidak perlu mengetahui detail cara aplikasi dirancang.

23633b02ac7ce1bc.png

3. Apa itu Profil Dasar Pengukuran

Profil Dasar Pengukuran meningkatkan kecepatan eksekusi kode sekitar 30% sejak peluncuran pertama dengan menghindari langkah interpretasi dan kompilasi tepat waktu (JIT) untuk jalur kode yang disertakan. Dengan mengirimkan Profil Dasar Pengukuran dalam aplikasi atau library, Android Runtime (ART) dapat mengoptimalkan jalur kode yang disertakan melalui kompilasi Ahead of Time (AOT), yang memberikan peningkatan performa untuk setiap pengguna baru dan setiap update aplikasi. Pengoptimalan yang dipandu profil (PGO) ini memungkinkan aplikasi mengoptimalkan startup, mengurangi jank interaksi, dan meningkatkan performa runtime secara keseluruhan untuk pengguna akhir sejak peluncuran pertama.

Dengan Profil Dasar Pengukuran, semua interaksi pengguna—seperti startup aplikasi, menavigasi antar-layar, atau men-scroll konten—lebih lancar sejak pertama kali dijalankan. Peningkatan kecepatan dan responsivitas aplikasi akan meningkatkan jumlah pengguna aktif harian dan rata-rata rasio pengunjung yang kembali yang lebih tinggi.

Profil Dasar Pengukuran membantu memandu pengoptimalan di luar startup aplikasi dengan menyediakan interaksi pengguna umum yang meningkatkan runtime aplikasi sejak peluncuran pertama. Kompilasi AOT yang dipandu tidak mengandalkan perangkat pengguna dan dapat dilakukan sekali per rilis pada mesin pengembangan, bukan perangkat seluler. Dengan mengirimkan rilis menggunakan Profil Dasar Pengukuran, pengoptimalan aplikasi akan tersedia jauh lebih cepat daripada hanya mengandalkan Profil Cloud.

Jika tidak menggunakan Profil Dasar Pengukuran, semua kode aplikasi dikompilasi secara JIT dalam memori setelah diinterpretasikan atau menjadi file odex di latar belakang saat perangkat tidak ada aktivitas. Pengguna mungkin akan memiliki pengalaman yang kurang optimal saat menjalankan aplikasi setelah menginstal atau mengupdate-nya untuk pertama kali sebelum jalur baru dioptimalkan.

4. Menyiapkan modul generator Profil Dasar Pengukuran

Anda dapat membuat Profil Dasar Pengukuran dengan class uji instrumentasi yang memerlukan modul Gradle baru untuk ditambahkan ke project Anda. Cara termudah untuk menambahkannya ke project Anda adalah dengan wizard modul Android Studio yang disertakan dengan Android Studio Hedgehog atau yang lebih tinggi.

Buka jendela wizard modul baru dengan mengklik kanan project atau modul Anda di panel Project dan pilih New > Module.

232b04efef485e9c.png

Dari jendela yang terbuka, pilih Baseline Profile Generator dari panel Template.

b191fe07969e8c26.png

Selain parameter biasa seperti nama modul, nama paket, bahasa, atau bahasa konfigurasi build, ada dua input yang tidak biasa untuk modul baru: Target application dan Use Gradle Managed Device.

Target application adalah modul aplikasi yang digunakan untuk membuat Profil Dasar Pengukuran. Jika Anda memiliki lebih dari satu modul aplikasi di project Anda, pilih modul mana yang ingin Anda gunakan untuk menjalankan generator.

Kotak centang Use Gradle Managed Device menyetel modul untuk menjalankan generator Profil Dasar Pengukuran pada emulator Android yang dikelola secara otomatis. Anda dapat membaca selengkapnya tentang Perangkat yang Dikelola Gradle di Menskalakan pengujian dengan Perangkat yang Dikelola Gradle. Jika Anda menghapus centang ini, generator akan menggunakan perangkat apa pun yang terhubung.

Setelah Anda menentukan semua detail tentang modul baru, klik Finish untuk melanjutkan pembuatan modul.

Perubahan yang dibuat oleh wizard modul

Wizard modul membuat beberapa perubahan pada project Anda.

Wizard ini menambahkan modul Gradle bernama baselineprofile atau nama yang Anda pilih pada wizard.

Modul ini menggunakan plugin com.android.test, yang memberi tahu Gradle untuk tidak menyertakannya dalam aplikasi Anda, sehingga hanya dapat berisi kode pengujian atau benchmark. Wizard ini juga menerapkan plugin androidx.baselineprofile, yang memungkinkan pembuatan Profil Dasar Pengukuran secara otomatis.

Wizard juga membuat perubahan pada modul aplikasi target yang Anda pilih. Secara khusus, wizard menerapkan plugin androidx.baselineprofile, menambahkan dependensi androidx.profileinstaller, dan menambahkan dependensi baselineProfile ke modul yang baru dibuat build.gradle(.kts):

plugins {
  id("androidx.baselineprofile")
}

dependencies {
  // ...
  implementation("androidx.profileinstaller:profileinstaller:1.3.0")
  "baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}

Menambahkan dependensi androidx.profileinstaller memungkinkan Anda melakukan hal berikut:

  • Secara lokal memverifikasi peningkatan performa dari Profil Dasar Pengukuran yang dibuat.
  • Menggunakan Profil Dasar Pengukuran di Android 7 (API level 24) dan Android 8 (API level 26), yang tidak mendukung profil Cloud.
  • Menggunakan Profil Dasar Pengukuran di perangkat yang tidak memiliki Layanan Google Play.

Dependensi baselineProfile(project(":baselineprofile")) memberi tahu Gradle dari modul mana Profil Dasar Pengukuran yang dibuat harus diambil.

Sekarang setelah project Anda siap, tulis class generator Profil Dasar Pengukuran.

5. Menulis generator Profil Dasar Pengukuran

Biasanya, Anda membuat Profil Dasar Pengukuran untuk perjalanan pengguna biasa pada aplikasi Anda.

Wizard modul membuat class pengujian BaselineProfileGenerator dasar yang mampu menghasilkan Profil Dasar Pengukuran untuk memulai aplikasi Anda dan terlihat seperti berikut:

@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {

    @get:Rule
    val rule = BaselineProfileRule()

    @Test
    fun generate() {
        rule.collect("com.example.baselineprofiles_codelab") {
            // This block defines the app's critical user journey. This is where you
            // optimize for app startup. You can also navigate and scroll
            // through your most important UI.

            // Start default activity for your app.
            pressHome()
            startActivityAndWait()

            // TODO Write more interactions to optimize advanced journeys of your app.
            // For example:
            // 1. Wait until the content is asynchronously loaded.
            // 2. Scroll the feed content.
            // 3. Navigate to detail screen.

            // Check UiAutomator documentation for more information about how to interact with the app.
            // https://d.android.com/training/testing/other-components/ui-automator
        }
    }
}

Class ini menggunakan aturan pengujian BaselineProfileRule dan berisi satu metode pengujian untuk membuat profil. Titik entri untuk membuat profil adalah fungsi collect(). Pengujian ini hanya memerlukan dua parameter:

  • packageName: paket aplikasi Anda.
  • profileBlock: parameter lambda terakhir.

Di lambda profileBlock, Anda menentukan interaksi yang mencakup perjalanan pengguna biasa pada aplikasi Anda. Library akan menjalankan profileBlock beberapa kali, mengumpulkan class dan fungsi yang dipanggil, dan membuat Profil Dasar Pengukuran di perangkat dengan kode yang akan dioptimalkan.

Secara default, class generator yang dibuat berisi interaksi untuk memulai Activity default Anda dan menunggu hingga frame pertama aplikasi Anda dirender menggunakan metode startActivityAndWait().

Memperpanjang generator dengan perjalanan kustom

Anda dapat melihat bahwa class yang dibuat juga menyertakan beberapa TODO untuk menulis lebih banyak interaksi guna mengoptimalkan perjalanan lanjutan aplikasi. Hal ini disarankan agar Anda dapat mengoptimalkan performa setelah aplikasi dimulai.

Di aplikasi contoh kami, Anda dapat mengidentifikasi perjalanan ini dengan melakukan hal berikut:

  1. Mulai aplikasi. Langkah ini sudah ditangani sebagian oleh class yang dibuat.
  2. Tunggu hingga konten dimuat secara asinkron.
  3. Men-scroll daftar camilan.
  4. Membuka detail camilan.

Ubah generator untuk memuat fungsi yang diuraikan yang mencakup perjalanan biasa dalam cuplikan berikut:

// ...
rule.collect("com.example.baselineprofiles_codelab") {
    // This block defines the app's critical user journey. This is where you
    // optimize for app startup. You can also navigate and scroll
    // through your most important UI.

    // Start default activity for your app.
    pressHome()
    startActivityAndWait()

    // TODO Write more interactions to optimize advanced journeys of your app.
    // For example:
    // 1. Wait until the content is asynchronously loaded.
    waitForAsyncContent()
    // 2. Scroll the feed content.
    scrollSnackListJourney()
    // 3. Navigate to detail screen.
    goToSnackDetailJourney()

    // Check UiAutomator documentation for more information about how to interact with the app.
    // https://d.android.com/training/testing/other-components/ui-automator
}
// ...

Sekarang, tulis interaksi untuk setiap perjalanan yang disebutkan. Anda dapat menulisnya sebagai fungsi ekstensi MacrobenchmarkScope sehingga Anda memiliki akses ke parameter dan fungsi yang disediakannya. Menulisnya dengan cara ini memungkinkan Anda menggunakan kembali interaksi dengan benchmark untuk memverifikasi peningkatan performa.

Menunggu konten asinkron

Banyak aplikasi memiliki semacam pemuatan asinkron saat startup aplikasi, juga dikenal sebagai status yang ditampilkan sepenuhnya, yang memberi tahu sistem saat konten dimuat dan dirender, dan pengguna dapat berinteraksi dengannya. Tunggu status di generator (waitForAsyncContent) dengan interaksi berikut:

  1. Temukan feed daftar camilan.
  2. Tunggu hingga beberapa item dalam daftar terlihat di layar.
fun MacrobenchmarkScope.waitForAsyncContent() {
   device.wait(Until.hasObject(By.res("snack_list")), 5_000)
   val contentList = device.findObject(By.res("snack_list"))
   // Wait until a snack collection item within the list is rendered.
   contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)
}

Perjalanan daftar scroll

Untuk scroll perjalanan daftar camilan (scrollSnackListJourney), Anda dapat mengikuti interaksi berikut:

  1. Menemukan elemen UI daftar camilan.
  2. Atur margin gestur agar tidak memicu navigasi sistem.
  3. Men-scroll daftar dan menunggu hingga UI selesai.
fun MacrobenchmarkScope.scrollSnackListJourney() {
   val snackList = device.findObject(By.res("snack_list"))
   // Set gesture margin to avoid triggering gesture navigation.
   snackList.setGestureMargin(device.displayWidth / 5)
   snackList.fling(Direction.DOWN)
   device.waitForIdle()
}

Membuka perjalanan detail

Perjalanan terakhir (goToSnackDetailJourney) menerapkan interaksi ini:

  1. Menemukan daftar camilan dan semua item camilan yang dapat Anda gunakan.
  2. Memilih item dari daftar.
  3. Mengklik item tersebut dan menunggu hingga layar detail dimuat. Anda dapat memanfaatkan fakta bahwa daftar camilan tidak akan muncul lagi di layar.
fun MacrobenchmarkScope.goToSnackDetailJourney() {
    val snackList = device.findObject(By.res("snack_list"))
    val snacks = snackList.findObjects(By.res("snack_item"))
    // Select snack from the list based on running iteration.
    val index = (iteration ?: 0) % snacks.size
    snacks[index].click()
    // Wait until the screen is gone = the detail is shown.
    device.wait(Until.gone(By.res("snack_list")), 5_000)
}

Setelah menentukan semua interaksi yang diperlukan agar generator Profil Dasar Pengukuran siap dijalankan, Anda perlu menentukan perangkat yang menjalankannya.

6. Menyiapkan perangkat untuk menjalankan generator

Untuk membuat Profil Dasar Pengukuran, sebaiknya gunakan emulator seperti Perangkat yang Dikelola Gradle atau perangkat yang menjalankan Android 13 (API 33) atau yang lebih tinggi.

Agar proses dapat direproduksi dan mengotomatiskan pembuatan Profil Dasar Pengukuran, Anda dapat menggunakan Perangkat yang Dikelola Gradle. Perangkat yang Dikelola Gradle memungkinkan Anda menjalankan pengujian pada emulator Android tanpa perlu meluncurkan dan menghancurkannya secara manual. Anda dapat mempelajari lebih lanjut tentang Perangkat yang Dikelola Gradle di Menskalakan pengujian dengan Perangkat yang Dikelola Gradle.

Untuk menentukan Perangkat yang Dikelola Gradle, tambahkan definisinya ke file build.gradle.kts modul :baselineprofile seperti ditunjukkan dalam cuplikan berikut:

android {
  // ...

  testOptions.managedDevices.devices {
    create<ManagedVirtualDevice>("pixel6Api31") {
        device = "Pixel 6"
        apiLevel = 31
        systemImageSource = "aosp"
    }
  }
}

Dalam hal ini, kita menggunakan Android 11 (API level 31) dan image sistem aosp mampu mengakses root.

Selanjutnya, konfigurasikan Plugin Profil Dasar Pengukuran Gradle untuk menggunakan Perangkat yang Dikelola Gradle dan sudah ditentukan. Untuk melakukannya, tambahkan nama perangkat ke dalam properti managedDevices dan nonaktifkan useConnectedDevices seperti ditunjukkan dalam cuplikan berikut:

android {
  // ...
}

baselineProfile {
   managedDevices += "pixel6Api31"
   useConnectedDevices = false
}

dependencies {
  // ...
}

Selanjutnya, buat Profil Dasar Pengukuran.

7. Membuat Profil Dasar Pengukuran

Setelah perangkat siap, Anda dapat membuat Profil Dasar Pengukuran. Plugin Profil Dasar Pengukuran Gradle membuat tugas Gradle untuk mengotomatiskan seluruh proses menjalankan class pengujian generator dan menerapkan profil dasar pengukuran yang dibuat ke aplikasi Anda.

Wizard modul baru membuat konfigurasi run agar dapat menjalankan tugas Gradle dengan cepat dan dengan semua parameter yang diperlukan agar dapat berjalan tanpa perlu beralih antara terminal dan Android Studio

Untuk menjalankannya, cari konfigurasi run Generate Baseline Profile dan klik tombol Run 599be5a3531f863b.png.

6911ecf1307a213f.png

Tugas tersebut memulai image emulator yang ditentukan sebelumnya. Jalankan interaksi dari class pengujian BaselineProfileGenerator beberapa kali, lalu hancurkan emulator dan berikan output ke Android Studio.

Setelah generator selesai dengan sukses, plugin Gradle akan secara otomatis menempatkan baseline-prof.txt yang dihasilkan ke dalam aplikasi target Anda (modul :app) di folder src/release/generated/baselineProfile/.

fa0f52de5d2ce5e8.png

(Opsional) Menjalankan generator dari command line

Atau, Anda dapat menjalankan generator dari command line. Anda dapat memanfaatkan tugas yang dibuat oleh Perangkat yang Dikelola Gradle—:app:generateBaselineProfile. Perintah ini menjalankan semua pengujian dalam project yang ditentukan oleh dependensi baselineProfile(project(:baselineProfile)). Karena modul ini juga berisi benchmark untuk verifikasi peningkatan performa nanti, pengujian tersebut gagal dengan peringatan untuk tidak menjalankan benchmark pada emulator.

android
   .testInstrumentationRunnerArguments
   .androidx.benchmark.enabledRules=BaselineProfile

Untuk itu, Anda dapat memfilter semua generator Profil Dasar Pengukuran dengan argumen runner instrumentasi berikut, dan semua benchmark dilewati:

Seluruh perintah terlihat seperti berikut:

./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

Mendistribusikan aplikasi Anda dengan Profil Dasar Pengukuran

Setelah Profil Dasar Pengukuran dibuat dan disalin ke dalam kode sumber aplikasi Anda, bangun versi produksi aplikasi seperti biasa. Anda tidak perlu melakukan apa pun lagi untuk mendistribusikan Profil Dasar Pengukuran ke pengguna. Profil akan dipilih oleh Plugin Android Gradle selama pembuatan dan disertakan dalam AAB atau APK Anda. Selanjutnya, upload build tersebut ke Google Play.

Saat pengguna menginstal aplikasi atau mengupdate aplikasi dari versi sebelumnya, Profil Dasar Pengukuran juga diinstal, menghasilkan performa yang lebih baik sejak pertama kali aplikasi dijalankan.

Langkah selanjutnya menunjukkan cara memverifikasi seberapa banyak peningkatan performa aplikasi dengan Profil Dasar Pengukuran.

8. (Opsional) Menyesuaikan pembuatan Profil Dasar Pengukuran

Plugin Profil Dasar Pengukuran Gradle menyertakan opsi untuk menyesuaikan cara pembuatan profil guna memenuhi kebutuhan spesifik Anda. Anda dapat mengubah perilaku dengan blok konfigurasi baselineProfile { } dalam skrip build.

Blok konfigurasi dalam modul :baselineprofile memengaruhi cara menjalankan generator dengan kemungkinan untuk menambahkan managedDevices dan memutuskan apakah akan useConnectedDevices atau perangkat yang Dikelola Gradle.

Blok konfigurasi dalam modul target :app memutuskan di mana profil akan disimpan atau bagaimana profil akan dibuat. Anda dapat mengubah parameter berikut:

  • automaticGenerationDuringBuild: jika diaktifkan, Anda dapat membuat Profil Dasar Pengukuran saat membangun rilis build. Hal ini berguna saat membangun di CI sebelum mengirimkan aplikasi Anda.
  • saveInSrc: menentukan apakah Profil Dasar Pengukuran yang dibuat disimpan dalam folder src/. Atau, Anda dapat mengakses file dari folder build :baselineprofile.
  • baselineProfileOutputDir: menentukan tempat untuk menyimpan Profil Dasar Pengukuran yang dibuat.
  • mergeIntoMain: secara default, Profil Dasar Pengukuran dibuat per varian build (ragam produk dan jenis build). Jika ingin menggabungkan semua profil menjadi src/main, Anda dapat melakukannya dengan mengaktifkan tanda ini.
  • filter: Anda dapat memfilter class atau metode yang akan disertakan atau dikecualikan dari Profil Dasar Pengukuran yang dibuat. Tindakan ini dapat bermanfaat bagi developer library yang hanya ingin menyertakan kode dari library.

9. Memverifikasi peningkatan performa startup

Setelah dibuat dan ditambahkan ke aplikasi, pastikan Profil Dasar Pengukuran memberi efek ke performa aplikasi sesuai harapan Anda.

Wizard modul baru membuat class benchmark bernama StartupBenchmarks. Wizard ini berisi benchmark untuk mengukur waktu startup aplikasi dan membandingkannya dengan saat aplikasi menggunakan Profil Dasar Pengukuran.

Class tersebut terlihat seperti berikut:

@RunWith(AndroidJUnit4::class)
@LargeTest
class StartupBenchmarks {

    @get:Rule
    val rule = MacrobenchmarkRule()

    @Test
    fun startupCompilationNone() =
        benchmark(CompilationMode.None())

    @Test
    fun startupCompilationBaselineProfiles() =
        benchmark(CompilationMode.Partial(BaselineProfileMode.Require))

    private fun benchmark(compilationMode: CompilationMode) {
        rule.measureRepeated(
            packageName = "com.example.baselineprofiles_codelab",
            metrics = listOf(StartupTimingMetric()),
            compilationMode = compilationMode,
            startupMode = StartupMode.COLD,
            iterations = 10,
            setupBlock = {
                pressHome()
            },
            measureBlock = {
                startActivityAndWait()

                // TODO Add interactions to wait for when your app is fully drawn.
                // The app is fully drawn when Activity.reportFullyDrawn is called.
                // For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
                // from the AndroidX Activity library.

                // Check the UiAutomator documentation for more information on how to
                // interact with the app.
                // https://d.android.com/training/testing/other-components/ui-automator
            }
        )
    }
}

Class tersebut menggunakan MacrobenchmarkRule yang mampu menjalankan benchmark untuk aplikasi Anda dan mengumpulkan metrik performa. Titik entri untuk menulis benchmark adalah fungsi measureRepeated dari aturan.

Fungsi ini membutuhkan beberapa parameter:

  • packageName: aplikasi mana yang akan diukur.
  • metrics: jenis informasi apa yang ingin Anda ukur selama benchmark.
  • iterations: berapa kali benchmark akan diulang.
  • startupMode: bagaimana Anda ingin aplikasi Anda dimulai pada awal benchmark Anda.
  • setupBlock: interaksi apa yang harus terjadi dengan aplikasi Anda sebelum pengukuran.
  • measureBlock: interaksi dengan aplikasi yang ingin Anda ukur selama benchmark.

Class pengujian juga berisi dua pengujian: startupCompilationeNone() dan startupCompilationBaselineProfiles(), yang memanggil fungsi benchmark() dengan compilationMode yang berbeda.

CompilationMode

Parameter CompilationMode menentukan cara aplikasi dikompilasi sebelumnya ke dalam kode mesin. Parameter ini memiliki opsi berikut:

  • DEFAULT: mengompilasi sebagian aplikasi terlebih dahulu menggunakan Profil Dasar Pengukuran jika tersedia. Kompilasi ini digunakan jika tidak ada parameter compilationMode yang diterapkan.
  • None(): mereset status kompilasi aplikasi dan tidak mengompilasi aplikasi terlebih dahulu. Kompilasi tepat waktu (JIT) masih diaktifkan selama eksekusi aplikasi.
  • Partial(): mengompilasi aplikasi terlebih dahulu dengan Profil Dasar Pengukuran atau menjalankan pemanasan, atau keduanya.
  • Full(): – mengompilasi seluruh kode aplikasi terlebih dahulu. Ini adalah satu-satunya opsi di Android 6 (API 23) dan yang lebih rendah.

Jika ingin mulai mengoptimalkan performa aplikasi, Anda dapat memilih mode kompilasi DEFAULT, karena performanya akan mirip dengan saat aplikasi diinstal dari Google Play. Jika ingin membandingkan manfaat performa yang diberikan Profil Dasar Pengukuran, Anda dapat melakukannya dengan membandingkan hasil mode kompilasi None dan Partial.

Mengubah benchmark untuk menunggu konten

Benchmark ditulis mirip dengan generator Profil Dasar Pengukuran dengan menulis interaksi dengan aplikasi Anda. Secara default, benchmark yang dibuat hanya menunggu frame pertama dirender. Cara ini serupa dengan cara BaselineProfileGenerator melakukannya, jadi sebaiknya Anda meningkatkannya untuk menunggu konten asinkron.

Anda dapat melakukannya dengan menggunakan kembali fungsi ekstensi yang Anda tulis untuk generator. Karena benchmark ini mencatat pengaturan waktu startup—dengan menggunakan StartupTimingMetric()—sebaiknya Anda hanya menyertakan menunggu konten asinkron di sini, lalu menulis benchmark terpisah untuk perjalanan pengguna lain yang ditentukan di generator.

// ...
measureBlock = {
   startActivityAndWait()

   // The app is fully drawn when Activity.reportFullyDrawn is called.
   // For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
   // from the AndroidX Activity library.
   waitForAsyncContent() // <------- Added to wait for async content.

   // Check the UiAutomator documentation for more information on how to
   // interact with the app.
   // https://d.android.com/training/testing/other-components/ui-automator
}

Menjalankan benchmark

Anda dapat menjalankan benchmark dengan cara yang sama seperti Anda menjalankan uji instrumentasi. Anda dapat menjalankan fungsi pengujian, atau seluruh class dengan ikon gutter di sampingnya.

587b04d1a76d1e9d.png

Pastikan Anda memilih perangkat fisik, karena menjalankan benchmark pada emulator Android akan gagal saat runtime dengan peringatan bahwa benchmark dapat memberikan hasil yang salah. Meskipun secara teknis Anda dapat menjalankannya di emulator, Anda hanya mengukur performa mesin host Anda. Jika bebannya berat, benchmark Anda akan berperforma lebih lambat, begitu pula sebaliknya.

94e0da86b6f399d5.png

Setelah Anda menjalankan benchmark, aplikasi akan dibangun ulang, kemudian menjalankan benchmark Anda. Benchmark akan memulai, menghentikan, dan bahkan menginstal ulang aplikasi Anda beberapa kali berdasarkan iterations yang Anda tentukan.

Setelah benchmark selesai, Anda dapat melihat pengaturan waktu di output Android Studio, seperti ditunjukkan di screenshot berikut:

282f90d5f6ff5196.png

Dari screenshot, Anda dapat melihat bahwa waktu startup aplikasi berbeda untuk setiap CompilationMode. Nilai median ditampilkan dalam tabel berikut:

timeToInitialDisplay [ms]

timeToFullDisplay [ms]

Tidak ada

202.2

818.8

BaselineProfiles

193.7

637.9

Peningkatan

4%

28%

Perbedaan antara mode kompilasi untuk timeToFullDisplay adalah 180 md, yaitu peningkatan sebesar ~28% dengan hanya memiliki Profil Dasar Pengukuran. CompilationNone berperforma lebih buruk karena perangkat harus melakukan kompilasi JIT paling banyak selama startup aplikasi. CompilationBaselineProfiles berperforma lebih baik karena kompilasi parsial dengan Profil Dasar Pengukuran AOT mengompilasi kode yang paling mungkin digunakan pengguna dan membiarkan kode non-kritis tidak dikompilasi sebelumnya sehingga tidak harus segera dimuat.

10. (Opsional) Memverifikasi peningkatan performa scroll

Mirip dengan langkah sebelumnya, Anda dapat mengukur dan memverifikasi performa scroll. Pertama, buat class pengujian ScrollBenchmarks dengan aturan benchmark dan dua metode pengujian yang menggunakan mode kompilasi berbeda:

@LargeTest
@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {

   @get:Rule
   val rule = MacrobenchmarkRule()

   @Test
   fun scrollCompilationNone() = scroll(CompilationMode.None())

   @Test
   fun scrollCompilationBaselineProfiles() = scroll(CompilationMode.Partial())

   private fun scroll(compilationMode: CompilationMode) {
       // TODO implement
   }
}

Dari dalam metode scroll, gunakan fungsi measureRepeated dengan parameter yang diperlukan. Untuk parameter metrics, gunakan FrameTimingMetric, yang mengukur berapa lama waktu yang diperlukan untuk menghasilkan frame UI:

private fun scroll(compilationMode: CompilationMode) {
   rule.measureRepeated(
       packageName = "com.example.baselineprofiles_codelab",
       metrics = listOf(FrameTimingMetric()),
       compilationMode = compilationMode,
       startupMode = StartupMode.WARM,
       iterations = 10,
       setupBlock = {
           // TODO implement
       },
       measureBlock = {
           // TODO implement
       }
   )
}

Kali ini, Anda perlu membagi interaksi lebih banyak di antara setupBlock dan measureBlock untuk hanya mengukur durasi frame selama tata letak pertama dan men-scroll konten. Oleh karena itu, tempatkan fungsi yang memulai layar default ke setupBlock, serta fungsi ekstensi yang sudah dibuat waitForAsyncContent() dan scrollSnackListJourney() ke measureBlock:

private fun scroll(compilationMode: CompilationMode) {
   rule.measureRepeated(
       packageName = "com.example.baselineprofiles_codelab",
       metrics = listOf(FrameTimingMetric()),
       compilationMode = compilationMode,
       startupMode = StartupMode.WARM,
       iterations = 10,
       setupBlock = {
           pressHome()
           startActivityAndWait()
       },
       measureBlock = {
           waitForAsyncContent()
           scrollSnackListJourney()
       }
   )
}

Setelah benchmark siap, Anda dapat menjalankannya seperti sebelumnya untuk mendapatkan hasil seperti yang ditunjukkan pada screenshot berikut:

84aa99247226fc3a.png

FrameTimingMetric menghasilkan durasi frame dalam milidetik (frameDurationCpuMs) pada persentil ke-50, ke-90, ke-95, dan ke-99. Di Android 12 (level API 31) dan yang lebih tinggi, kode ini juga menampilkan berapa lama frame Anda melebihi batas (frameOverrunMs). Nilainya bisa negatif, yang berarti ada waktu tambahan yang tersisa untuk menghasilkan frame.

Dari hasil tersebut dapat dilihat bahwa CompilationBaselineProfiles memiliki rata-rata durasi frame yang lebih pendek sebesar 2 md, yang mungkin tidak terlihat oleh pengguna. Namun, untuk persentil lainnya, hasilnya lebih jelas. Untuk P99, perbedaannya adalah 43,5 md, yang berarti lebih dari 3 frame yang dilewati di perangkat yang beroperasi pada 90 FPS. Misalnya, untuk Pixel 6, waktu maksimumnya adalah 1.000 md/90 FPS = ~11 md untuk merender frame.

11. Selamat

Selamat, Anda berhasil menyelesaikan codelab ini dan meningkatkan performa aplikasi Anda dengan Profil Dasar Pengukuran.

Referensi lainnya

Lihat referensi tambahan berikut:

Dokumen referensi