Android 6.0 (level API 23) dan yang lebih tinggi mendukung API pelacakan native, trace.h
,
untuk menulis peristiwa rekaman aktivitas ke buffer sistem yang kemudian dapat Anda analisis menggunakan
Perfetto atau systrace. Contoh kasus penggunaan umum untuk API ini mencakup pengamatan waktu
yang diperlukan blok kode tertentu untuk menjalankan dan mengaitkan blok kode
dengan perilaku sistem yang tidak diinginkan.
Catatan: Pada perangkat dan emulator yang menjalankan API level 27 dan yang lebih rendah, jika
memori yang tersedia tidak mencukupi atau memori terlalu terfragmen, Anda akan mendapatkan
pesan berikut: Atrace could not allocate enough memory to record a trace
.
Jika hal ini terjadi dan rekaman Anda tidak memiliki kumpulan data yang lengkap, Anda
harus menutup proses latar belakang atau memulai ulang perangkat atau emulator.
Untuk menentukan peristiwa kustom yang terjadi pada kode native dalam aplikasi atau game Anda, selesaikan langkah-langkah berikut:
Tentukan pointer fungsi untuk fungsi ATrace yang Anda gunakan untuk mengambil peristiwa kustom dalam aplikasi atau game Anda, seperti yang ditampilkan pada cuplikan kode berikut:
#include <android/trace.h> #include <dlfcn.h> void *(*ATrace_beginSection) (const char* sectionName); void *(*ATrace_endSection) (void); typedef void *(*fp_ATrace_beginSection) (const char* sectionName); typedef void *(*fp_ATrace_endSection) (void);
Muat simbol ATrace saat waktu proses, seperti yang ditampilkan pada cuplikan kode berikut. Biasanya, Anda menjalankan proses ini pada pembuat objek.
// Retrieve a handle to libandroid. void *lib = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL); // Access the native tracing functions. if (lib != NULL) { // Use dlsym() to prevent crashes on devices running Android 5.1 // (API level 22) or lower. ATrace_beginSection = reinterpret_cast<fp_ATrace_beginSection>( dlsym(lib, "ATrace_beginSection")); ATrace_endSection = reinterpret_cast<fp_ATrace_endSection>( dlsym(lib, "ATrace_endSection")); }
Perhatian: Untuk alasan keamanan, sertakan panggilan ke
dlopen()
hanya dalam versi debug aplikasi atau game Anda.Catatan: Untuk memberikan dukungan pelacakan hingga pada Android 4.3 (level API 18), Anda dapat menggunakan JNI guna memanggil metode dalam kode terkelola di sekitar kode yang ditampilkan pada cuplikan sebelumnya.
Panggil
ATrace_beginSection()
danATrace_endSection()
di awal dan akhir peristiwa kustom Anda:#include <android/trace.h> char *customEventName = new char[32]; sprintf(customEventName, "User tapped %s button", buttonName); ATrace_beginSection(customEventName); // Your app or game's response to the button being pressed. ATrace_endSection();
Catatan: Saat Anda memanggil
ATrace_beginSection()
beberapa kali, memanggilATrace_endSection()
hanya akan mengakhiri metodeATrace_beginSection()
yang terakhir dipanggil. Jadi, untuk panggilan bertingkat, pastikan Anda mencocokkan dengan tepat setiap panggilan keATrace_beginSection()
dengan panggilan keATrace_endSection()
.Selain itu, Anda tidak dapat memanggil
ATrace_beginSection()
di satu thread dan mengakhirinya di thread lain. Anda harus memanggil kedua fungsi dari thread yang sama.
Tips untuk memudahkan
Tips berikut dapat Anda lakukan untuk memudahkan proses analisis kode native Anda.
Melacak seluruh fungsi
Saat melakukan instrumentasi stack panggilan atau pengaturan waktu fungsi, melacak seluruh
fungsi mungkin akan bermanfaat. Anda dapat menggunakan makro ATRACE_CALL()
untuk menjadikan jenis
pelacakan ini lebih mudah disiapkan. Selain itu, makro semacam itu memungkinkan Anda melewati
pembuatan blok try
dan catch
dalam berbagai kasus yang mana fungsi yang dilacak mungkin
memberikan pengecualian atau panggilan return
lebih awal.
Untuk membuat makro guna melacak seluruh fungsi, selesaikan langkah-langkah berikut:
Tentukan makro:
#define ATRACE_NAME(name) ScopedTrace ___tracer(name) // ATRACE_CALL is an ATRACE_NAME that uses the current function name. #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) class ScopedTrace { public: inline ScopedTrace(const char *name) { ATrace_beginSection(name); } inline ~ScopedTrace() { ATrace_endSection(); } };
Panggil makro pada fungsi yang ingin Anda lacak:
void myExpensiveFunction() { ATRACE_CALL(); // Code that you want to trace. }
Memberi nama thread Anda
Anda dapat memberi nama untuk setiap thread di tempat peristiwa terjadi, seperti yang diperlihatkan pada cuplikan kode berikut. Langkah ini memudahkan identifikasi thread yang termasuk dalam tindakan spesifik dalam game Anda.
#include <pthread.h> static void *render_scene(void *parm) { // Code for preparing your app or game's visual components. } static void *load_main_menu(void *parm) { // Code that executes your app or game's main logic. } void init_threads() { pthread_t render_thread, main_thread; pthread_create(&render_thread, NULL, render_scene, NULL); pthread_create(&main_thread, NULL, load_main_menu, NULL); pthread_setname_np(render_thread, "MyRenderer"); pthread_setname_np(main_thread, "MyMainMenu"); }
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Praktik terbaik untuk performa SQLite
- Membuat dan mengukur Profil Dasar Pengukuran tanpa Macrobenchmark