Android 6.0(API 수준 23) 이상에서는 네이티브 추적 API(trace.h
)를 지원합니다. 이 API는 이후 Perfetto나 systrace를 사용하여 분석할 수 있는 트레이스 이벤트를 시스템 버퍼에 기록합니다. 이 API의 일반적인 사용 사례로는 특정 코드 블록을 실행하는 데 소요되는 시간을 관찰하고 코드 블록을 원치 않는 시스템 동작에 연결하는 작업이 있습니다.
참고: API 수준 27 이하를 실행하는 기기 및 에뮬레이터에서 사용 가능한 메모리가 충분하지 않거나 메모리가 과도하게 세분화되어 있으면 Atrace could not allocate enough memory to record a trace
라는 메시지가 표시됩니다.
이러한 메시지가 표시되고 전체 데이터 세트가 캡처에 없으면 백그라운드 프로세스를 닫거나 기기 또는 에뮬레이터를 다시 시작해야 합니다.
앱 또는 게임 내의 네이티브 코드에서 발생하는 맞춤 이벤트를 정의하려면 다음 단계를 완료하세요.
다음 코드 스니펫에서와 같이 앱이나 게임 내의 맞춤 이벤트를 캡처하는 데 사용하는 ATrace 함수의 함수 포인터를 정의합니다.
#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);
다음 코드 스니펫에서와 같이 런타임 시 ATrace 기호를 로드합니다. 일반적으로 객체 생성자에서 이 프로세스를 실행합니다.
// 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")); }
주의: 보안상의 이유로 디버그 버전의 앱 또는 게임에만
dlopen()
호출을 포함하세요.참고: Android 4.3(API 수준 18)까지 추가로 추적 지원을 제공하려면 JNI를 사용하여 앞의 스니펫에 표시된 코드 주위의 관리 코드에서 메서드를 호출하면 됩니다.
맞춤 이벤트의 시작과 끝에서 각각
ATrace_beginSection()
및ATrace_endSection()
을 호출합니다.#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();
참고:
ATrace_beginSection()
을 여러 번 호출하는 경우ATrace_endSection()
을 호출하면 가장 최근에 호출된ATrace_beginSection()
메서드만 종료됩니다. 따라서 중첩 호출의 경우 각ATrace_beginSection()
호출이ATrace_endSection()
호출과 올바르게 일치하는지 확인하세요.또한 하나의 스레드에서
ATrace_beginSection()
을 호출했다가 다른 스레드에서 종료할 수 없습니다. 두 함수를 모두 동일한 스레드에서 호출해야 합니다.
편의 도움말
다음 도움말은 선택사항이지만 이를 통해 네이티브 코드를 보다 쉽게 분석할 수 있습니다.
전체 함수 추적
호출 스택 또는 함수 타이밍을 계측할 때 전체 함수를 추적하는 것이 유용할 수 있습니다. ATRACE_CALL()
매크로를 사용하여 이 유형의 추적을 보다 쉽게 설정할 수 있습니다. 또한 이와 같이 매크로를 사용하면 추적된 함수가 예외를 발생시키거나 return
을 조기에 호출하는 경우에 try
및 catch
블록 생성을 건너뛸 수 있습니다.
전체 함수를 추적하기 위한 매크로를 만들려면 다음 단계를 완료하세요.
다음과 같이 매크로를 정의합니다.
#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(); } };
추적할 함수 내에서 매크로를 호출합니다.
void myExpensiveFunction() { ATRACE_CALL(); // Code that you want to trace. }
스레드 이름 지정
다음 코드 스니펫에 설명된 대로 이벤트가 발생하는 각 스레드에 이름을 지정할 수 있습니다. 이 단계를 통해 게임 내 특정 작업에 속하는 스레드를 쉽게 확인할 수 있습니다.
#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"); }
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- SQLite 성능 권장사항
- Macrobenchmark 없이 기준 프로필 생성 및 측정