Di Android 16 (API level 36) dan yang lebih tinggi, ProfilingManager memungkinkan Anda mengambil
profil secara otomatis sebagai respons terhadap pemicu sistem, seperti error Aplikasi Tidak
Merespons (ANR), error Kehabisan Memori (OutOfMemoryError), atau peristiwa
startup aplikasi. Karena Anda tidak dapat memprediksi kapan banyak peristiwa ini akan terjadi
di lapangan, memulai perekaman secara manual terlebih dahulu tidaklah praktis. Dengan
profiling berbasis pemicu, sistem akan mengelola perekaman dan mengirimkan
profil yang dihasilkan ke aplikasi Anda sehingga Anda dapat:
- Men-debug masalah stabilitas: Mendiagnosis ANR dan kebocoran memori yang tidak dapat diprediksi.
- Mengoptimalkan perjalanan penting pengguna (CUJ): Analisis alur seperti startup
aplikasi (
TRIGGER_TYPE_COLD_STARTdanTRIGGER_TYPE_APP_FULLY_DRAWN). - Memahami perilaku pengguna: Periksa peristiwa seperti keluar dari aplikasi yang dimulai oleh pengguna.
Untuk mengetahui daftar lengkap pemicu yang tersedia, lihat ProfilingTrigger.
Jenis pemicu
Pemicu berbeda dalam cara sistem menangkap profil saat peristiwa terjadi.
Pemicu yang menggunakan trace latar belakang
Banyak pemicu—seperti ANR—merupakan konsekuensi dari masalah sebelumnya. Memulai trace hanya setelah sistem mendeteksi ANR akan melewatkan pekerjaan pemblokiran yang menyebabkan ANR. Untuk merekam aktivitas yang mengarah ke peristiwa, pemicu berikut menyimpan snapshot trace latar belakang aktif sistem. Jika tidak ada pelacakan latar belakang yang berjalan saat peristiwa terjadi, tidak ada profil yang dikumpulkan:
TRIGGER_TYPE_ANR(API level 36)TRIGGER_TYPE_APP_FULLY_DRAWN(API level 36)TRIGGER_TYPE_APP_REQUEST_RUNNING_TRACE(API level 36.1)TRIGGER_TYPE_KILL_FORCE_STOP(API level 36.1)TRIGGER_TYPE_KILL_RECENTS(API level 36.1)TRIGGER_TYPE_KILL_TASK_MANAGER(API level 36.1)TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE(API level 37)
Pemicu yang memulai pengambilan baru
Pemicu berikut tidak bergantung pada pelacakan latar belakang. Sebagai gantinya, sistem akan memulai pengambilan profil baru saat peristiwa terjadi:
TRIGGER_TYPE_COLD_START(API level 37)TRIGGER_TYPE_OOM(API level 37)
Pemicu yang perilaku perekamannya bervariasi menurut anomali
Untuk pemicu anomali berikut, jenis profil yang diambil (menyimpan snapshot rekaman aktivitas latar belakang yang aktif atau memulai pengambilan baru) dan perilaku pembatasan kapasitas bergantung pada anomali spesifik yang dideteksi oleh sistem:
TRIGGER_TYPE_ANOMALY(API level 37)TRIGGER_TYPE_APP_COMPAT(API level 37)
Menyiapkan pemicu
Kode berikut menunjukkan cara mendaftar untuk
pemicu TRIGGER_TYPE_APP_FULLY_DRAWN dan menetapkan periode tunggu untuk pemicu tersebut.
Kotlin
@RequiresApi(Build.VERSION_CODES.BAKLAVA) fun recordWithTrigger() { val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) ?: return val triggers = ArrayList<ProfilingTrigger>() val triggerBuilder = ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN) .setRateLimitingPeriodHours(1) triggers.add(triggerBuilder.build()) val callbackExecutor: Executor = Executors.newSingleThreadExecutor() val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.resultFilePath ) setupProfileUploadWorker(profilingResult.resultFilePath) } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage ) } } profilingManager.registerForAllProfilingResults(callbackExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers) Choreographer.getInstance().postFrameCallback { frameTimeNanos -> // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. reportFullyDrawn() } }
Java
public void recordWithTrigger() { ProfilingManager profilingManager = getApplicationContext().getSystemService( ProfilingManager.class); List<ProfilingTrigger> triggers = new ArrayList<>(); ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder( ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN); triggerBuilder.setRateLimitingPeriodHours(1); triggers.add(triggerBuilder.build()); Executor callbackExecutor = Executors.newSingleThreadExecutor(); Consumer<ProfilingResult> resultCallback = new Consumer<ProfilingResult>() { @Override public void accept(ProfilingResult profilingResult) { if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.getResultFilePath()); setupProfileUploadWorker(profilingResult.getResultFilePath()); } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.getErrorCode() + " errormsg=" + profilingResult.getErrorMessage()); } } }; profilingManager.registerForAllProfilingResults(callbackExecutor, resultCallback); profilingManager.addProfilingTriggers(triggers); Choreographer.getInstance().postFrameCallback((f) -> { // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. reportFullyDrawn(); }); }
Kode ini melakukan langkah-langkah berikut:
- Mendapatkan pengelola: Mengambil layanan
ProfilingManager. - Menentukan pemicu: Mem-build
ProfilingTriggeruntukTRIGGER_TYPE_APP_FULLY_DRAWN. Peristiwa ini terjadi saat aplikasi memanggilreportFullyDrawn()selama cold start yang dimulai aktivitas untuk melaporkan bahwa aplikasi telah selesai memulai dan bersifat interaktif. - Menetapkan periode tunggu pemicu: Menerapkan periode tunggu 1 jam ke pemicu khusus ini menggunakan
setRateLimitingPeriodHoursselain pembatas kapasitas sistem. Periode tunggu ini mencegah aplikasi merekam lebih dari satu profil startup per jam. - Daftarkan pemroses: Memanggil
registerForAllProfilingResultsuntuk menentukan callback yang menangani hasil. Callback ini menerima jalur profil yang disimpan melaluigetResultFilePath(). - Menambahkan pemicu: Mendaftarkan daftar pemicu ke
ProfilingManagermenggunakanaddProfilingTriggers. - Peristiwa pengaktifan: Memposting callback frame
Choreographeryang memanggilreportFullyDrawn()setelah frame berikutnya digambar, yang memunculkan peristiwaTRIGGER_TYPE_APP_FULLY_DRAWNke sistem, sehingga memicu pengumpulan profil dengan asumsi pelacakan latar belakang sistem sedang berjalan dan kuota pembatas kapasitas tersedia. Agar pemicu ini terjadi, pastikan aplikasi Anda memanggilreportFullyDrawn().
Siklus proses pemicu
Pemicu yang terdaftar akan tetap ada setiap kali aplikasi dimulai ulang dan sistem di-reboot. Anda tidak perlu
mendaftarkan ulang pemicu setiap kali aplikasi dimulai atau setelah sistem
dimulai ulang—setelah Anda mendaftarkan pemicu menggunakan addProfilingTriggers, sistem
akan mempertahankannya secara otomatis untuk aplikasi Anda hingga Anda menghapusnya atau
aplikasi di-uninstal.
Kapan harus membatalkan pendaftaran pemicu
Karena pemicu yang terdaftar tetap ada saat aplikasi dimulai ulang dan sistem dimulai ulang,
melewati addProfilingTriggers pada peluncuran berikutnya tidak akan menghentikan pemicu
yang terdaftar di sesi sebelumnya. Untuk berhenti merekam profil untuk peristiwa tertentu
atau untuk semua peristiwa, panggil removeProfilingTriggersByType atau
clearProfilingTriggers secara eksplisit.
Batalkan pendaftaran pemicu dalam situasi berikut:
- Menargetkan kelompok atau me-roll back flag jarak jauh: Anda dapat melakukan segmentasi profil di seluruh kelompok menggunakan konfigurasi jarak jauh atau flag pengujian A/B. Setiap kali perangkat keluar dari kelompok sampel atau tanda dinonaktifkan, batalkan pendaftaran pemicu.
- Menyelesaikan kampanye proses debug: Setelah Anda mengumpulkan cukup profil untuk mendiagnosis masalah atau mengirimkan perbaikan, hapus pemicu. Membatalkan pendaftaran pemicu yang tidak diperlukan akan menghemat penyimpanan perangkat dan kuota pembatas kapasitas aplikasi Anda untuk permintaan pembuatan profil lainnya.
Siklus proses callback
Tidak seperti permintaan pembuatan profil langsung, profil berbasis pemicu hanya memberikan hasil ke pemroses global yang terdaftar di registerForAllProfilingResults. Dalam
callback, panggil ProfilingResult.getTriggerType untuk mengidentifikasi pemicu
yang memulai pengambilan, dan panggil
ProfilingResult.getResultFilePath untuk menemukan file profil yang disimpan. Untuk
mengetahui detail tentang nama file profil pemicu, mengambil file dengan adb, dan mengupload
hasil di latar belakang, lihat Mengambil dan mengupload profil.
Meskipun pemicu tetap ada saat aplikasi dimulai ulang dan sistem dimulai ulang, callback hasil Anda tidak akan tetap ada. Daftarkan callback Anda di Executor latar belakang setelah startup aplikasi selesai (agar Anda tidak memperlambat cold start) untuk menerima profil dalam kedua skenario berikut:
- Saat aplikasi Anda berjalan: Untuk pemicu yang tidak menghentikan atau membuat aplikasi Anda error, sistem akan memanggil callback Anda pada
Executoryang disediakan saat pemicu terjadi dan profil disimpan. Setelah penghentian aplikasi: Untuk pemicu yang sering melibatkan atau mendahului penghentian aplikasi (seperti
TRIGGER_TYPE_ANR,TRIGGER_TYPE_OOM, atauTRIGGER_TYPE_KILL_RECENTS), atau jika aplikasi Anda berhenti sebelum pengambilan selesai, sistem akan menyimpan profil di latar belakang dan mengantrekan hasilnya di seluruh proses mulai ulang aplikasi dan mulai ulang sistem. Sistem akan mempertahankan hasil antrean yang tidak terkirim hingga 7 hari dan mengirimkannya saat aplikasi Anda berjalan dan memanggilregisterForAllProfilingResultsdi lain waktu.
Cara kerja pelacakan latar belakang
Untuk menyeimbangkan overhead pembuatan profil dengan pengambilan artefak yang berguna, sistem tidak menjalankan pelacakan latar belakang secara terus-menerus. Sebagai gantinya, alat ini mengambil sampel secara berkala dengan memulai pelacakan latar belakang pada interval acak.
Rekaman aktivitas latar belakang yang dipicu sistem menggunakan ring buffer dengan ukuran maksimum yang ditentukan sistem. Saat buffer terisi, data rekaman aktivitas baru akan menimpa data terlama. Seperti yang ditunjukkan pada Gambar 1, saat pemicu terdaftar diaktifkan saat pelacakan latar belakang aktif dan kuota pembatas kapasitas tersedia, sistem akan menyimpan ringkasan ring buffer yang berisi aktivitas terbaru yang mengarah ke pemicu.
Menetapkan jeda khusus pemicu
Pemicu frekuensi tinggi dapat dengan cepat menghabiskan kuota pembatas kapasitas aplikasi Anda.
Untuk mencegah satu jenis pemicu menghabiskan kuota Anda, gunakan
setRateLimitingPeriodHours untuk menambahkan periode tunggu minimum per pemicu
di atas pembatas kapasitas sistem.
Men-debug pemicu secara lokal
Karena pelacakan latar belakang berjalan pada interval acak dalam produksi, pengujian pemicu secara lokal memerlukan pemaksaan pelacakan latar belakang berkelanjutan dan mengabaikan pembatas kapasitas tingkat sistem untuk paket Anda (setiap cooldown per pemicu yang ditetapkan dengan setRateLimitingPeriodHours masih berlaku, dan rate_limiter.disabled hanya berlaku untuk panggilan requestProfiling yang didorong aplikasi).
Untuk perintah adb guna memaksa pelacakan latar belakang, menyimulasikan pemicu dari
command line, dan memeriksa status layanan, lihat Memaksa pengaktifan pelacakan latar belakang untuk
pengujian pemicu di Perintah debug untuk pembuatan profil lokal.