Library Jetpack Benchmark memungkinkan Anda menjalankan benchmark dengan cepat terhadap kode berbasis Java atau Kotlin dari dalam Android Studio. Library ini menangani pemanasan, mengukur performa kode dan jumlah alokasi, serta menampilkan hasil benchmark ke konsol Android Studio dan file JSON dengan lebih detail.
Kasus penggunaan mencakup men-scroll RecyclerView
, menjalankan kueri database, dan
mengukur bagian lambat kode yang ingin Anda jadikan lebih cepat.
Anda dapat menggunakan library dalam lingkungan continuous integration (CI), seperti yang dijelaskan dalam Menjalankan benchmark dalam Continuous Integration.
Jika Anda belum menggunakan AndroidX dalam project yang ingin diukur, lihat Melakukan migrasi project yang ada menggunakan Android Studio.
Panduan memulai
Bagian ini memberikan serangkaian langkah cepat untuk mencoba menjalankan benchmark tanpa harus memindahkan kode ke dalam modul. Karena langkah-langkahnya melibatkan penonaktifan proses debug untuk hasil performa yang akurat, Anda tidak akan melakukan perubahan pada sistem kontrol sumber, tetapi hal tersebut masih dapat membantu saat ingin menjalankan pengukuran satu kali.
Untuk menjalankan benchmark satu kali dengan cepat, lakukan hal berikut:
Tambahkan library ke file
build.gradle
modul Anda:project_root/module_dir/build.gradle
Groovy
dependencies { androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.1.0-alpha13' }
Kotlin
dependencies { androidTestImplementation("androidx.benchmark:benchmark-junit4:1.1.0-alpha13") }
Untuk menonaktifkan proses debug di manifes pengujian, update elemen
<application>
untuk menonaktifkan paksa proses debug sementara seperti berikut:project_root/module_dir/src/androidTest/AndroidManifest.xml
<!-- Important: disable debuggable for accurate performance results --> <application android:debuggable="false" tools:ignore="HardcodedDebugMode" tools:replace="android:debuggable"/>
Untuk menambahkan benchmark, tambahkan instance dari
BenchmarkRule
dalam file pengujian di direktoriandroidTest
. Untuk informasi selengkapnya tentang menulis benchmark, lihat Menulis benchmark.Cuplikan kode berikut ini menunjukkan cara menambahkan benchmark ke pengujian JUnit:
Kotlin
@RunWith(AndroidJUnit4::class) class MyBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() = benchmarkRule.measureRepeated { doSomeWork() } }
Java
@RunWith(AndroidJUnit4.class) class MyBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { doSomeWork(); } } }
Waktu untuk menjalankan benchmark
Sebaiknya buat profil kode Anda sebelum menulis benchmark. Ini akan membantu Anda menemukan operasi berharga yang dapat dioptimalkan. Tindakan ini juga dapat mengetahui mengapa operasi lambat dengan menunjukkan hal yang terjadi saat operasi berjalan. Contohnya dapat mencakup berjalan di thread prioritas rendah, tidur karena akses disk, atau panggilan telepon yang tidak terduga ke fungsi yang berharga, seperti decoding bitmap.
Menambahkan titik pelacakan khusus melalui API TraceCompat
(atau -ktx
wrapper) memungkinkan Anda melihatnya di
CPU Profiler Android Studio atau Systrace:
Kotlin
fun proccessBitmap(bitmap: Bitmap): Bitmap { trace("processBitmap") { // perform work on bitmap... } }
Java
public Bitmap processBitmap(Bitmap bitmaptest) { TraceCompat.beginSection("processBitmap"); try { // perform work on bitmap... } finally { TraceCompat.endSection(); } }
Apa saja yang perlu diukur
Benchmark sangat berguna untuk tugas CPU yang dijalankan berkali-kali di aplikasi Anda. Contoh
yang baik adalah men-scroll RecyclerView
, konversi/pemrosesan data, dan potongan
kode yang digunakan berulang kali.
Jenis kode yang lain lebih sulit diukur dengan benchmark. Karena benchmark berjalan dalam sebuah loop, semua kode yang jarang dijalankan atau berperforma berbeda saat dipanggil beberapa kali, mungkin tidak sesuai untuk benchmark.
Menyimpan ke cache
Coba hindari pengukuran hanya cache. Misalnya, benchmark tata letak tampilan kustom mungkin hanya mengukur performa cache tata letak. Untuk menghindarinya, Anda dapat meneruskan parameter tata letak yang berbeda di setiap loop. Dalam kasus lain, seperti saat mengukur performa sistem file, tindakan ini mungkin sulit karena OS menyimpan cache sistem file sementara dalam sebuah loop.
Kode yang jarang dijalankan
Kode yang dijalankan satu kali selama memulai aplikasi kecil kemungkinannya untuk dikompilasi secara JIT oleh Android Runtime (ART). Oleh karena itu, menjalankan benchmark pada kode ini dengan microbenchmark, saat dijalankan dalam loop yang ketat, bukanlah cara yang realistis untuk mengetahui performanya.
Untuk menjalankan benchmark pada kode semacam ini, kami merekomendasikan Jetpack Macrobenchmark, yang mendukung pengukuran interaksi pengguna tingkat lebih tinggi, seperti peluncuran aplikasi dan performa scroll.
Penyiapan project lengkap
Agar dapat menyiapkan benchmark untuk benchmark reguler bukan benchmark satu kali,
Anda harus memisahkan benchmark ke dalam modulnya masing-masing. Tindakan ini memastikan
konfigurasi modul, seperti menetapkan debuggable
ke false
, terpisah
dari pengujian reguler.
Sebelum menambahkan modul benchmark, tempatkan kode dan resource yang ingin Anda ukur ke dalam modul library jika belum ada.
Contoh kami menunjukkan bagaimana menyiapkan project dengan cara tersebut.
Menyiapkan properti Android Studio
Jika menggunakan Android Studio 3.5, Anda harus menetapkan properti Android Studio secara manual untuk mengaktifkan dukungan wizard modul benchmark. Tindakan ini tidak diperlukan untuk Android Studio 3.6 atau yang lebih tinggi.
Untuk mengaktifkan template Android Studio pada benchmark, lakukan hal berikut:
Di Android Studio 3.5, klik Help > Edit Custom Properties.
Tambahkan baris berikut ke file yang terbuka:
npw.benchmark.template.module=true
Simpan dan tutup file tersebut.
Mulai ulang Android Studio.
Membuat modul baru
Template modul benchmark akan secara otomatis mengonfigurasi setelan untuk benchmark.
Untuk menggunakan template modul guna membuat modul baru, lakukan hal berikut:
Klik kanan project atau modul Anda, kemudian pilih New > Module.
Pilih Benchmark Module lalu klik Next.
Gambar 1. Modul benchmark
Masukkan nama modul, pilih bahasa, dan klik Finish.
Modul dibuat dan telah dikonfigurasi sebelumnya untuk benchmark, dengan menambahkan direktori benchmark serta menetapkan
debuggable
kefalse
.
Menulis tolok ukur
Benchmark adalah pengujian instrumentasi standar. Untuk membuat benchmark, gunakan
class BenchmarkRule
yang disediakan oleh library. Untuk menjalankan benchmark aktivitas, gunakan
ActivityTestRule
atau ActivityScenarioRule
. Untuk menjalankan benchmark kode UI,
gunakan @UiThreadTest
.
Kode berikut menunjukkan benchmark contoh:
Kotlin
@RunWith(AndroidJUnit4::class) class ViewBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun simpleViewInflate() { val context = ApplicationProvider.getApplicationContext<Context>() val inflater = LayoutInflater.from(context) val root = FrameLayout(context) benchmarkRule.measureRepeated { inflater.inflate(R.layout.test_simple_view, root, false) } } }
Java
@RunWith(AndroidJUnit4::class) public class ViewBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void simpleViewInflate() { Context context = ApplicationProvider.getApplicationContext<Context>(); final BenchmarkState state = benchmarkRule.getState(); LayoutInflater inflater = LayoutInflater.from(context); FrameLayout root = new FrameLayout(context); while (state.keepRunning()) { inflater.inflate(R.layout.test_simple_view, root, false); } } }
Anda dapat menonaktifkan pengaturan waktu untuk bagian kode yang tidak ingin diukur, seperti yang ditunjukkan pada contoh kode berikut:
Kotlin
@Test fun bitmapProcessing() = benchmarkRule.measureRepeated { val input: Bitmap = runWithTimingDisabled { constructTestBitmap() } processBitmap(input) }
Java
@Test public void bitmapProcessing() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { state.pauseTiming(); Bitmap input = constructTestBitmap(); state.resumeTiming(); processBitmap(input); } }
Untuk informasi tentang menjalankan benchmark, lihat Menjalankan benchmark.
Menjalankan benchmark
Di Android Studio, jalankan benchmark seperti halnya @Test
. Di Android
Studio 3.4 dan yang lebih tinggi, Anda dapat melihat output yang dikirim ke konsol.
Untuk menjalankan benchmark, dalam modul, buka benchmark/src/androidTest
lalu
tekan Control
+Shift
+F10
(Command
+Shift
+R
di Mac). Hasil benchmark
akan ditampilkan di konsol seperti yang ditunjukkan pada Gambar 2:
Gambar 2. Output benchmark di Android Studio
Dari command line, jalankan connectedCheck
reguler:
./gradlew benchmark:connectedCheck
Mengumpulkan data
Laporan benchmark lengkap dengan metrik tambahan dan informasi perangkat tersedia dalam format JSON.
Plugin Gradle androidx.benchmark
mengaktifkan output JSON secara default. Untuk
mengaktifkan output JSON secara manual di lingkungan build non-Gradle, teruskan
argumen instrumentasi, androidx.benchmark.output.enable
, lalu tetapkan ke true
.
Berikut adalah contoh menggunakan perintah adb shell am instrument
:
adb shell am instrument -w -e "androidx.benchmark.output.enable" "true" com.android.foo/androidx.benchmark.junit4.AndroidBenchmarkRunner
Secara default, laporan JSON ditulis ke disk di perangkat dalam folder download bersama eksternal APK pengujian, yang biasanya terletak di:
/storage/emulated/0/Download/app_id-benchmarkData.json
Anda dapat mengonfigurasi lokasi tempat laporan benchmark disimpan pada perangkat
menggunakan argumen instrumentasi additionalTestOutputDir
.
adb shell am instrument -w -e "androidx.benchmark.output.enable" "true" -e "additionalTestOutputDir" "/path_to_a_directory_on_device_test_has_write_permissions_to/" com.android.foo/androidx.benchmark.junit4.AndroidBenchmarkRunner
Laporan JSON akan disalin dari perangkat ke host. Laporan tersebut ditulis pada mesin host di:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/app_id-benchmarkData.json
Android Gradle Plugin 3.6 dan yang lebih baru
Saat menjalankan benchmark dari command line dengan Gradle, project yang menggunakan
Android Gradle Plugin 3.6 dan yang lebih baru dapat menambahkan flag berikut ke
file gradle.properties
project:
android.enableAdditionalTestOutput=true
Tindakan ini akan mengaktifkan fitur Android Gradle Plugin eksperimental untuk mengambil laporan benchmark dari perangkat yang menjalankan API 16 dan yang lebih tinggi.
Android Gradle Plugin 3.5 dan yang lebih lama
Bagi pengguna Android Gradle Plugin versi yang lebih lama, plugin Gradle androidx.benchmark
akan menangani penyalinan laporan benchmark JSON dari perangkat ke host.
Saat menggunakan AGP 3.5 atau yang lebih lama dan menargetkan API level 29 atau yang lebih tinggi,
Anda harus menambahkan flag ke manifes Android di direktori androidTest
dari
benchmark untuk mengaktifkan perilaku penyimpanan eksternal lama.
<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Untuk informasi selengkapnya, lihat Memilih tidak menggunakan penyimpanan terbatas untuk sementara.
Stabilitas frekuensi CPU
Frekuensi CPU pada perangkat seluler berubah secara dinamis dari kondisi tinggi (untuk performa) ke kondisi rendah (untuk menghemat daya, atau saat perangkat menjadi panas). Frekuensi yang bervariasi ini dapat membuat hasil benchmark sangat bervariasi, sehingga library memberikan cara untuk mengatasi masalah ini.
Mengunci frekuensi CPU (membutuhkan root)
Mengunci frekuensi CPU adalah cara terbaik untuk mendapatkan performa yang stabil. Cara ini memastikan bahwa frekuensi CPU
tidak terlalu tinggi sehingga membuat panas perangkat, atau rendah jika benchmark tidak sepenuhnya
menggunakan CPU. Meskipun ini adalah cara terbaik untuk memastikan performa yang stabil,
sebagian besar perangkat tidak mendukungnya karena memerlukan root adb
.
Untuk mengunci frekuensi CPU, tambahkan plugin helper yang disediakan ke classpath
project level teratas pada file build.gradle
utama:
Groovy
buildscript { ... dependencies { ... classpath "androidx.benchmark:benchmark-gradle-plugin:1.1.0-alpha13" } }
Kotlin
buildscript { ... dependencies { ... classpath("androidx.benchmark:benchmark-gradle-plugin:1.1.0-alpha13") } }
Terapkan plugin dalam build.gradle
modul benchmark Anda:
Groovy
plugins { id 'com.android.app' id 'androidx.benchmark' } ...
Kotlin
plugins { id("com.android.app") id("androidx.benchmark") ... }
Tindakan ini akan menambahkan tugas Gradle benchmark ke project Anda, termasuk
./gradlew lockClocks
dan ./gradlew unlockClocks
. Gunakan tugas ini untuk mengunci dan
membuka kunci CPU perangkat menggunakan adb.
Jika memiliki beberapa perangkat yang terlihat oleh adb, gunakan ANDROID_SERIAL
variabel lingkungan
untuk menentukan perangkat mana saja yang harus dijalankan oleh tugas Gradle di:
ANDROID_SERIAL=device-id-from-adb-devices ./gradlew lockClocks
Mode performa berkelanjutan
Window.setSustainedPerformanceMode()
adalah fitur yang didukung oleh beberapa
perangkat yang memungkinkan aplikasi memilih frekuensi CPU maksimal yang lebih rendah. Saat berjalan
di perangkat yang didukung, library Benchmark akan menggunakan kombinasi API ini dan
lmeluncurkan aktivitasnya sendiri untuk mencegah penurunan frekuensi karena panas dan menstabilkan
hasil.
Fungsionalitas ini diaktifkan secara default oleh testInstrumentationRunner
yang disetel oleh plugin Gradle. Jika ingin menggunakan runner kustom, Anda dapat membuat subclass
AndroidBenchmarkRunner
dan menggunakannya sebagai testInstrumentationRunner
.
Runner meluncurkan aktivitas layar penuh buram untuk memastikan bahwa benchmark berjalan di latar depan dan tidak ada penggambaran aplikasi lain.
Penjedaan eksekusi otomatis
Jika penguncian frekuensi CPU atau performa berkelanjutan digunakan, library akan secara otomatis melakukan deteksi penurunan frekuensi karena panas. Jika diaktifkan, benchmark internal akan berjalan secara berkala untuk menentukan kapan suhu perangkat cukup tinggi yang akan menurunkan performa CPU. Ketika penurunan performa CPU terdeteksi, library akan menjeda eksekusi untuk mendinginkan perangkat, dan mencoba kembali benchmark saat ini.
Error Konfigurasi
Library akan mendeteksi kondisi berikut guna memastikan project dan lingkungan Anda telah disiapkan untuk performa akurat rilis:
Debuggable
disetel kefalse
.- Perangkat fisik, bukan emulator, sedang digunakan.
- Frekuensi CPU terkunci jika perangkat di-root.
- Tingkat daya baterai di perangkat memadai.
Jika salah satu pemeriksaan di atas gagal, benchmark akan memberikan pesan error untuk mencegah pengukuran yang tidak akurat.
Untuk mengubah error tersebut menjadi peringatan, dan mencegahnya memberikan pesan error
sehingga menghentikan benchmark, teruskan jenis error yang ingin Anda ubah dalam
daftar yang dipisahkan koma ke argumen instrumentasi androidx.benchmark.suppressErrors
:
adb shell am instrument -w -e "androidx.benchmark.suppressErrors" "DEBUGGABLE" com.android.foo/androidx.benchmark.junit4.AndroidBenchmarkRunner
Yang dapat Anda tetapkan di Gradle sebagai berikut:
Groovy
android { defaultConfig { testInstrumentationRunnerArgument 'androidx.benchmark.suppressErrors', 'DEBUGGABLE' } }
Kotlin
android { defaultConfig { testInstrumentationRunnerArguments(mapOf( "androidx.benchmark.suppressErrors" to "DEBUGGABLE" )) } }
Perlu diperhatikan bahwa mengubah error memungkinkan benchmark berjalan dalam keadaan
yang tidak terkonfigurasi dengan benar, tetapi output dari benchmark akan secara sengaja dirusak
dengan menambahkan nama pengujian dengan error tersebut. Artinya, menjalankan benchmark
yang dapat di-debug dengan penggantian seperti di atas akan menambahkan nama pengujian
dengan DEBUGGABLE_
.
Pembuatan profil
Anda dapat membuat profil benchmark untuk menyelidiki mengapa kode yang diukur berjalan lambat.
Tambahkan kode berikut ini ke file build.gradle
modul benchmark:
Groovy
android { defaultConfig { // must be one of: 'None', 'StackSampling', or 'MethodTracing' testInstrumentationRunnerArgument 'androidx.benchmark.profiling.mode', 'StackSampling' } }
Kotlin
android { defaultConfig { // must be one of: 'None', 'StackSampling', or 'MethodTracing' testInstrumentationRunnerArgument = mapOf( "androidx.benchmark.profiling.mode", "StackSampling" ) } }
Saat Anda menjalankan benchmark, file .trace
output akan disalin ke host, dalam
direktori di samping hasil JSON. Buka file ini dengan Android Studio
menggunakanFile - Open untuk memeriksa hasil pembuatan profil di CPU Profiler.
Pelacakan metode
Dengan pelacakan metode, benchmark akan melakukan pemanasan sebelum menangkap pelacakan metode, mencatat setiap metode yang dipanggil oleh benchmark Anda. Perlu diperhatikan bahwa hasil performa akan dipengaruhi secara signifikan oleh overhead pengambilan setiap masuk/keluar metode.
Pengambilan sampel stack
Dengan pengambilan sampel stack, benchmark akan mengambil sampel stack panggilan, setelah warmup selesai. Anda dapat mengontrol frekuensi sampel dan durasi pengambilan sampel menggunakan argumen instrumentasi.
Di Android 10 (API 29) dan yang lebih tinggi, pengambilan sampel stack menggunakan Simpleperf untuk mengambil sampel callstack aplikasi, termasuk kode C++. Di Android 9 (API 28) dan yang lebih rendah, Debug.startMethodTracingSampling digunakan untuk mengambil sampel stack.
Untuk membaca selengkapnya cara menggunakan pelacakan dan pengambilan sampel metode, lihat konfigurasi pembuatan profil CPU.
Contoh benchmark
Kode benchmark contoh tersedia di project berikut:
Project contoh meliputi:
BenchmarkSample: ini adalah contoh mandiri, yang menunjukkan cara menggunakan modul benchmark untuk mengukur kode dan UI.
PagingWithNetworkSample: Contoh Komponen Arsitektur Android, yang menunjukkan cara mengukur performa
RecyclerView
.WorkManagerSample: Contoh Komponen Arsitektur Android, yang menunjukkan cara mengukur pekerja
WorkManager
.
Referensi lainnya
Untuk mempelajari lebih lanjut tentang Benchmark, lihat referensi tambahan berikut.
Blog
Berikan masukan
Untuk melaporkan masalah atau mengirimkan permintaan fitur saat menggunakan benchmark, lihat Issue Tracker publik.