Profil Baseline

Profil Baseline adalah daftar class dan metode yang disertakan dalam APK yang digunakan oleh Android Runtime (ART) selama penginstalan untuk melakukan prakompilasi jalur penting ke kode mesin. Ini adalah bentuk pengoptimalan yang dipandu profil (PGO) yang memungkinkan aplikasi mengoptimalkan startup, mengurangi jank, dan meningkatkan performa untuk pengguna akhir.

Cara kerja Profil Baseline

Aturan profil dikompilasi menjadi bentuk biner dalam APK, di assets/dexopt/baseline.prof.

Selama penginstalan, ART melakukan kompilasi metode Ahead-of-time (AOT) pada profil, sehingga metode tersebut dieksekusi lebih cepat. Jika profil berisi metode yang digunakan dalam peluncuran aplikasi atau selama rendering frame, pengguna akan mendapatkan waktu peluncuran yang lebih cepat dan/atau mengurangi jank.

Saat mengembangkan aplikasi atau library, sebaiknya tentukan Profil Baseline untuk mencakup jalur panas tertentu selama perjalanan penting pengguna ketika waktu rendering atau latensi penting, seperti mulai, transisi, atau scroll.

Kemudian, Profil Baseline dikirimkan langsung ke pengguna (melalui Google Play) bersama APK, seperti yang ditunjukkan pada gambar 1:

Gambar 1. Diagram ini menampilkan alur kerja profil baseline dari upload hingga pengiriman ke pengguna akhir, dan bagaimana alur kerja tersebut berkaitan dengan profil cloud.

Alasan menggunakan Profil Baseline

Waktu mulai adalah komponen penting untuk meningkatkan interaksi pengguna dengan aplikasi Anda. Peningkatan kecepatan dan responsivitas aplikasi akan meningkatkan jumlah pengguna aktif harian dan rata-rata rasio kunjungan kembali yang lebih tinggi.

Profil Cloud juga mengoptimalkan interaksi yang sama, tetapi hanya tersedia bagi pengguna sehari atau lebih setelah update dirilis dan tidak mendukung Android 7 (API 24) hingga Android 8 (API 26).

Perilaku kompilasi di seluruh versi Android

Versi Platform Android telah menggunakan pendekatan kompilasi aplikasi yang berbeda, masing-masing dengan kompromi performa yang terkait. Profil baseline meningkatkan metode kompilasi sebelumnya dengan menyediakan profil untuk semua penginstalan.

Versi Android Metode kompilasi Pendekatan pengoptimalan
Android 5 (API level 21) hingga Android 6 (API level 23) AOT Penuh Seluruh aplikasi dioptimalkan selama penginstalan, sehingga menyebabkan waktu tunggu yang lama untuk menggunakan aplikasi, peningkatan penggunaan RAM dan ruang disk, serta waktu yang lebih lama untuk memuat kode dari disk, yang berpotensi meningkatkan waktu cold startup.
Android 7 (API level 24) hingga Android 8.1 (API level 27) AOT Sebagian (Profil Baseline) Profil Baseline diinstal oleh androidx.profileinstaller saat pertama kali dijalankan, saat modul aplikasi menentukan dependensi ini. ART dapat meningkatkan hal ini lebih lanjut dengan menambahkan aturan profil tambahan selama penggunaan aplikasi dan mengompilasinya saat perangkat sedang tidak digunakan. Tindakan ini mengoptimalkan ruang dan waktu disk untuk memuat kode dari disk, sehingga mengurangi waktu tunggu aplikasi.
Android 9 (API level 28) dan yang lebih tinggi AOT Sebagian (Profil Baseline + Cloud) Play menggunakan Profil Baseline selama penginstalan aplikasi untuk mengoptimalkan APK dan profil Cloud (jika tersedia). Setelah penginstalan, profil ART akan diupload ke Play dan digabungkan, lalu disediakan sebagai Profil Cloud kepada pengguna lain saat mereka menginstal/mengupdate aplikasi.

Membuat Profil Baseline

Buat aturan profil secara otomatis menggunakan BaselineProfileRule

Sebagai developer aplikasi, Anda dapat otomatis membuat profil untuk setiap rilis aplikasi menggunakan library Jetpack Macrobenchmark.

Untuk membuat Profil Baseline menggunakan library Macrobenchmark:

  1. Tambahkan dependensi ke library ProfileInstaller di build.gradle aplikasi Anda untuk mengaktifkan kompilasi Profil Baseline lokal dan Play Store. Ini adalah satu-satunya cara untuk melakukan sideload Profil Baseline secara lokal.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.2.0-beta01")
    }
    
  2. Siapkan modul Macrobenchmark dalam project gradle Anda.

  3. Tentukan pengujian baru bernama BaselineProfileGenerator yang terlihat seperti:

    @ExperimentalBaselineProfilesApi
    @RunWith(AndroidJUnit4::class)
    class BaselineProfileGenerator {
        @get:Rule val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() =
            baselineProfileRule.collectBaselineProfile(packageName = "com.example.app") {
                pressHome()
                // This block defines the app's critical user journey. Here we are interested in
                // optimizing for app startup. But you can also navigate and scroll
                // through your most important UI.
                startActivityAndWait()
            }
    }
    
  4. Hubungkan emulator userdebug atau Proyek Open Source Android (AOSP) yang di-root yang menjalankan Android 9 atau yang lebih tinggi.

  5. Jalankan perintah adb root dari terminal untuk memastikan daemon adb berjalan dengan izin root.

  6. Jalankan pengujian dan tunggu hingga selesai.

  7. Menemukan lokasi profil yang dihasilkan di logcat. Telusuri tag log Benchmark.

    com.example.app D/Benchmark: Usable output directory: /storage/emulated/0/Android/media/com.example.app
    
    # List the output baseline profile
    ls /storage/emulated/0/Android/media/com.example.app
    SampleStartupBenchmark_startup-baseline-prof.txt
    
  8. Ambil file yang dihasilkan dari perangkat.

    adb pull storage/emulated/0/Android/media/com.example.app/SampleStartupBenchmark_startup-baseline-prof.txt .
    
  9. Ganti nama file yang dihasilkan menjadi baseline-prof.txt, lalu salin ke direktori src/main modul aplikasi Anda.

Menentukan aturan profil secara manual

Anda dapat menentukan aturan profil secara manual di aplikasi atau modul library dengan membuat file bernama baseline-prof.txt yang berada di direktori src/main. Ini adalah folder yang sama yang berisi file AndroidManifest.xml.

File tersebut menentukan satu aturan per baris. Setiap aturan mewakili pola untuk metode atau class yang cocok di aplikasi atau library yang perlu dioptimalkan.

Sintaksis untuk aturan ini adalah superset dari format profil ART (HRF) yang dapat dibaca manusia saat menggunakan adb shell profman --dump-classes-and-methods. Sintaksisnya sangat mirip dengan sintaksis untuk deskripsi dan tanda tangan, tetapi juga memungkinkan karakter pengganti menyederhanakan proses penulisan aturan.

Contoh berikut menunjukkan beberapa aturan Profil Baseline yang disertakan dalam library Jetpack Compose:

HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;

Sintaksis aturan

Aturan ini menggunakan salah satu dari dua bentuk untuk ditarget, yaitu metode atau class:

[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]

Aturan class menggunakan pola berikut:

[CLASS_DESCRIPTOR]
Sintaksis Deskripsi
FLAGS Mewakili satu atau beberapa karakter H, S, dan P untuk menunjukkan apakah metode ini harus ditandai sebagai Hot, Startup, atau Post Startup terkait dengan jenis startup.

Metode dengan tanda H menunjukkan bahwa metode tersebut "panas", yang berarti metode tersebut akan dipanggil beberapa kali sepanjang waktu penggunaan aplikasi.

Metode dengan tanda S menunjukkan bahwa metode ini dipanggil saat startup.

Metode dengan tanda P menunjukkan bahwa metode panas ini tidak terkait dengan startup.

Class yang ada dalam file ini menunjukkan bahwa class digunakan saat memulai dan harus dialokasikan sebelumnya di heap untuk menghindari biaya pemuatan class. Compiler ART menggunakan berbagai strategi pengoptimalan, seperti kompilasi AOT metode ini dan melakukan pengoptimalan tata letak di file AOT yang dihasilkan.
CLASS_DESCRIPTOR Deskripsi untuk class metode yang ditargetkan. Misalnya, androidx.compose.runtime.SlotTable akan memiliki deskripsi Landroidx/compose/runtime/SlotTable;. Catatan: L ditambahkan di sini sesuai format Dalvik Executable (DEX).
METHOD_SIGNATURE Tanda tangan metode, termasuk nama, jenis parameter, dan jenis pengembalian metode. Misalnya, metode

// LayoutNode.kt

fun isPlaced():Boolean {
// ...
}

pada LayoutNode memiliki tanda tangan isPlaced()Z.

Pola ini dapat memiliki karakter pengganti agar memiliki satu aturan yang mencakup beberapa metode atau class. Untuk mendapatkan bantuan terpandu saat menulis dengan sintaksis aturan di Android Studio, lihat plugin Profil Baseline Android .

Contoh aturan karakter pengganti mungkin terlihat seperti ini:

HSPLandroidx/compose/ui/layout/**->**(**)**

Jenis yang didukung dalam aturan profil baseline

Aturan Profil Baseline mendukung jenis berikut. Untuk detail tentang jenis ini, lihat Format Dalvik Executable (DEX).

Karakter Jenis Deskripsi
B byte Byte bertanda tangan
C karakter Poin kode karakter unicode yang dienkode dalam UTF-16
D ganda Nilai floating point presisi ganda
F float Nilai floating point presisi tunggal
I int Bilangan Bulat
J panjang Bilangan bulat panjang
S video singkat Bertanda tangan singkat
V void Void
Z boolean Benar atau salah
L (nama class) referensi Instance nama class

Selain itu, library dapat menentukan aturan yang akan dikemas dalam artefak AAR. Saat Anda mem-build APK untuk menyertakan artefak ini, aturan digabungkan (serupa dengan cara penggabungan manifes dilakukan) dan dikompilasi ke profil ART biner ringkas yang khusus untuk APK.

ART memanfaatkan profil ini jika APK digunakan di perangkat untuk mengompilasi AOT subset aplikasi tertentu pada waktu penginstalan di Android 9 (API level 28), atau Android 7 (API level 24) saat menggunakan ProfileInstaller.

Catatan tambahan

Saat membuat Profil Baseline, ada beberapa hal tambahan yang perlu diperhatikan:

  • Android 5 hingga Android 6 (API level 21 dan 23) sudah mengompilasi AOT APK pada waktu penginstalan.

  • Aplikasi yang dapat di-debug tidak pernah dikompilasi AOT untuk membantu pemecahan masalah.

  • File aturan harus diberi nama baseline-prof.txt dan ditempatkan di direktori utama set sumber utama Anda (harus berupa file pasangan ke file AndroidManifest.xml Anda)

  • File ini hanya akan digunakan jika Anda menggunakan Plugin Android Gradle 7.1.0-alpha05 atau yang lebih baru (Android Studio Bumblebee Canary 5).

  • Bazel saat ini tidak mendukung pembacaan dan penggabungan Profil Baseline ke dalam APK.

  • Profil Baseline tidak boleh lebih besar dari 1,5 MB setelah dikompresi. Oleh karena itu, library dan aplikasi harus berusaha menentukan sekumpulan kecil aturan profil yang memaksimalkan dampak.

  • Aturan luas yang mengompilasi terlalu banyak aplikasi dapat memperlambat startup karena peningkatan akses disk. Anda harus menguji performa Profil Baseline.

Mengukur peningkatan

Mengotomatiskan pengukuran dengan library Macrobenchmark

Macrobenchmark memungkinkan Anda mengontrol kompilasi pra-pengukuran melalui CompilationMode API, termasuk penggunaan BaselineProfile.

Jika sudah menyiapkan pengujian BaselineProfileRule dalam modul Macrobenchmark, Anda dapat menentukan pengujian baru dalam modul tersebut untuk mengevaluasi performanya:

@RunWith(AndroidJUnit4::class)
class BaselineProfileBenchmark {
  @get:Rule
  val benchmarkRule = MacrobenchmarkRule()

  @Test
  fun startupNoCompilation() {
    startup(CompilationMode.None())
  }

  @Test
  fun startupBaselineProfile() {
    startup(CompilationMode.Partial(
      baselineProfileMode = BaselineProfileMode.Require
    ))
  }

  private fun startup(compilationMode: CompilationMode) {
    benchmarkRule.measureRepeated(
      packageName = "com.example.app",
      metrics = listOf(StartupTimingMetric()),
      iterations = 10,
      startupMode = StartupMode.COLD,
      compilationMode = compilationMode
    ) { // this = MacrobenchmarkScope
        pressHome()
        startActivityAndWait()
    }
  }
}

Contoh hasil pengujian yang lulus dapat dilihat pada gambar 2:

Gambar 2. Ini adalah hasil pengujian kecil. Aplikasi yang lebih besar akan mendapatkan manfaat yang lebih baik dari Profil Baseline.

Catatan, meskipun contoh di atas melihat StartupTimingMetric, ada metrik penting lainnya yang patut dipertimbangkan, seperti Jank (Metrik frame), yang dapat diukur menggunakan Jetpack Macrobenchmark.

Mengukur peningkatan aplikasi secara manual

Pertama, mari kita ukur startup aplikasi yang tidak dioptimalkan untuk referensi.

PACKAGE_NAME=com.example.app
# Force Stop App
adb shell am force-stop $PACKAGE_NAME
# Reset compiled state
adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup
# This corresponds to `Time to initial display` metric
# For additional info https://developer.android.com/topic/performance/vitals/launch-time#time-initial
adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \
 | grep "TotalTime"

Selanjutnya, mari men-sideload Profil Baseline.

# Unzip the Release APK first
unzip release.apk
# Create a ZIP archive
# Note: The name should match the name of the APK
# Note: Copy baseline.prof{m} and rename it to primary.prof{m}
cp assets/dexopt/baseline.prof primary.prof
cp assets/dexopt/baseline.profm primary.profm
# Create an archive
zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files:
unzip -l release.dm
# Archive:  release.dm
#   Length      Date    Time    Name
# ---------  ---------- -----   ----
#      3885  1980-12-31 17:01   primary.prof
#      1024  1980-12-31 17:01   primary.profm
# ---------                     -------
#                               2 files
# Install APK + Profile together
adb install-multiple release.apk release.dm

Untuk memastikan bahwa paket dioptimalkan saat penginstalan, jalankan perintah berikut:

# Check dexopt state
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME

Output harus menyatakan bahwa paket dikompilasi.

[com.example.app]
  path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
  arm64: [status=speed-profile] [reason=install-dm]

Sekarang, kita dapat mengukur performa startup aplikasi seperti sebelumnya, tetapi tanpa menyetel ulang status kompilasi.

# Force Stop App
adb shell am force-stop $PACKAGE_NAME
# Measure App startup
adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \
 | grep "TotalTime"

Masalah Umum

Saat ini, menggunakan Profil Baseline memiliki beberapa masalah umum:

  • Profil Baseline tidak dikemas dengan benar saat membuat APK dari app bundle. Untuk mengatasi masalah ini, terapkan com.android.tools.build:gradle:7.3.0-beta02 dan yang lebih tinggi (masalah).

  • Profil Baseline hanya dikemas dengan benar untuk file classes.dex utama. Hal ini memengaruhi aplikasi yang memiliki lebih dari satu file .dex. Untuk mengatasi masalah ini, terapkan com.android.tools.build:gradle:7.3.0-beta02 dan yang lebih tinggi (masalah).

  • Macrobenchmark tidak kompatibel dengan Profil Baseline di Android 12L (API 32) (masalah) dan Android 13 (API 33) (masalah).

  • Mereset cache profil ART tidak diizinkan di build user (non-root). Untuk mengatasi hal ini, androidx.benchmark:benchmark-macro-junit4:1.1.0-rc02 menyertakan perbaikan yang menginstal ulang aplikasi selama benchmark (masalah).

  • Profiler Android Studio tidak menginstal Profil Baseline saat membuat profil aplikasi (masalah).

  • Sistem build non-Gradle (Bazel, Buck, dll.) saat ini tidak mendukung kompilasi Profil Baseline menjadi APK output.

  • Play Store saat ini memerlukan waktu 10-14 jam setelah upload AAB untuk membuat Profil Baseline tersedia saat penginstalan. Pengguna yang mendownload aplikasi selama waktu ini tidak akan mendapatkan manfaat hingga dexopt latar belakang dijalankan (kemungkinan dalam semalam). Hal ini sedang diperbaiki secara aktif.

  • Saluran distribusi aplikasi non-Play Store mungkin tidak mendukung penggunaan Profil Baseline saat penginstalan. Pengguna aplikasi melalui saluran ini tidak akan mendapatkan manfaat hingga dexopt latar belakang dijalankan (kemungkinan dalam semalam).