런타임 성능 문제를 추적하는 프로파일러다.
Android Runtime이라 하면 애플리케이션의 자바/코틀린 코드를 컴파일하여 실행하는, CPU 점유의 영역인 것 같다. 프로세스(간단히 말해 애플리케이션)의 CPU 점유를 최적화하면 더 빠르고, 원활한 사용자 환경 제공, 기기 배터리 수명 보존 등의 이점이 있다.
"CPU 프로파일러를 사용하여 앱과 상호작용하는 동안 앱의 CPU 사용량 및 스레드 활동을 실시간으로 검사하거나 기록된 메서드 트레이스, 함수 트레이스, 시스템 트레이스의 세부정보를 검사할 수 있습니다."
트레이서 개념을 잘 모르겠다. 중점적으로 공부해야겠다.
CPU 프로파일러에서 기록하고 표시하는 정보의 구체적인 종류는 선택한 Recording configuration에 따라 결정된다.
1. System trace
앱에서 시스템 리소스와 상호작용하는 방법을 검사할 수 있는 정보를 캡처합니다.
2. Method trace
앱 프로세스의 각 스레드에 관해 일정 기간 실행되는 메서드(Java) 또는 함수(C/C++)가 실행 중 사용하는 CPU 리소스를 확인할 수 있습니다. 메서드 트레이스를 사용하여 호출자와 피호출자를 식별할 수도 있습니다. 호출자는 다른 메서드를 호출하는 메서드이고 피호출자는 다른 메서드에 의해 호출되는 메서드입니다. 이 정보를 사용하면 리소스 소모가 많은 특정 작업을 너무 자주 호출하는 메서드를 확인하고 리팩터링하여 불필요한 작업을 피할 수 있습니다.
CPU Profiler
-
Event timeline
- Shows the activities in your app as they transition through different states in their lifecycle
- indicates user interactions with the device, including screen rotation events.
-
CPU timeline
- Shows real-time CPU usage of your app—as a percentage of total available CPU time and the total number of threads your app is using.
- also shows the CPU usage of other processes (such as system processes or other apps), so you can compare it to your app’s usage.
- can inspect historical CPU usage data by moving your mouse along the horizontal axis of the timeline.
-
Thread activity timeline
- Lists each thread that belongs to your app process and
- indicates their activity along a timeline using the colors listed below.
- After you record a trace, you can select a thread from this timeline to inspect its data in the trace pane.
- Green(run or ready)
The thread is active or is ready to use the CPU. That is, it's in a running or runnable state.
- Yellow(wait)
The thread is active, but it’s waiting on an I/O operation, such as disk or network I/O, before it can complete its work.
- Gray(pause)
The thread is sleeping and is not consuming any CPU time. This sometimes occurs when the thread requires access to a resource that is not yet available. Either the thread goes into voluntary sleep, or the kernel puts the thread to sleep until the required resource becomes available.
- The CPU Profiler also reports CPU usage of threads that Android Studio and the Android platform add to your app process(JDWP, Profile Saver, Studio:VMStats, Studio:Perfa, and Studio:Heartbeat) — (although, the exact names displayed in the thread activity timeline may vary). Android Studio reports this data so that you can identify when thread activity and CPU usage are actually caused by "your app’s code"
Record traces
- 트레이스 기록을 시작하려면 CPU 프로파일러 위나 아래의 드롭다운 메뉴에서 기록 구성(System trace 또는 Method trace)을 선택하고 Record를 클릭
- 앱과 상호작용한 다음 완료되면 Stop을 클릭하면 아래와 같이 프로파일러의 트레이스 창에 트레이스 정보가 자동으로 표시된다.
- 아래 이미지는 메서드 트레이스를 기록한 후의 CPU 프로파일러
- Selected range
기록된 시간 중 트레이스 창에서 검사할 부분을 결정
- Interaction section
사용자 상호작용 및 앱 수명 주기 이벤트를 타임라인을 따라 표시
- Thread section
타임라인을 따라 모든 스레드의 스레드 상태 활동(예: 실행 중, 일시정지 등) 및 Call Chart(또는 시스템 트레이스의 트레이스 이벤트 차트)가 표시
- Analysis pane
선택한 기간 및 스레드 또는 메서드 호출에 관한 트레이스 데이터를 표시
- Analysis pane tabs
트레이스 세부정보를 표시하는 방법을 선택
- Time reference menu
각 호출의 경과 시간이 측정되는 방법을 결정(자바 메서드 샘플링/추적에서만 지원).
- Wall clock time
실제 경과 시간
- Thread time
타이밍 정보가 실제 경과 시간에서 스레드가 CPU 리소스를 소비하지 않는 시간을 뺀 시간을 나타낸다. Thread Time을 사용하면 주어진 메서드나 함수에 의해 소비되는 스레드의 실제 CPU 사용량을 더 효과적으로 파악할 수 있다.
- Filter
함수, 메서드, 클래스, 패키지 이름을 기준으로 트레이스 데이터를 필터링
Record CPU activity during app startup
앱이 시작하는 동안 CPU 활동을 자동으로 기록하려면 다음 단계를 따라야 한다.
- Run > Edit Configurations를 선택합니다.
- Profiling 탭에서 Start recording a method trace on startup 옆의 체크박스를 선택 합니다.
- 메뉴에서 CPU 기록 구성을 선택합니다.
- Apply를 클릭합니다.
- Run > Profile을 선택하여 Android 8.0(API 수준 26) 이상을 실행하는 기기에 앱을 배포합니다.
Export/Import traces
CPUT 활동을 기록한 후 데이터를 .trace 파일로 내보내기/가져오기 할 수 있다.
Inspect traces
Method traces :
- Threads 타임라인에서 직접 Call Chart를 볼 수 있다.
- Analysis 창에서 Flame Chart, Top Down, Bottom Up, Events탭을 볼 수 있다.
System traces :
- Threads 타임라인에서 직접 Trace Events를 볼 수 있다.
- Analysis 창에서 Flame Chart, Top Down, Bottom Up, Events 탭을 볼 수 있다.
Call Chart, Trace Events, Flame Chart, Top down 등 다양한 트레이스 확인 방법이 존재한다.
Method trace를 확인하는 Thread timeline의 Call Chart를 보자.
Inspect traces using the "Call Chart" :
- Method traces가 그래픽으로 표시된다.
- 가로축 : 호출의 기간과 타이밍 표시
- 메서드의 Self time
- 메서드의 Children time
- 메서드의 Total time
- 세로축 : 피호출자 표시
- 주황색 : System API 호출
- 녹색 : 앱 자체의 메서드 호출
- 파란색 : 타사 API 호출
Generate Trace Logs by Instrumenting Your App
- To generate a method trace of your app's execution, you can instrument your app using the Debug class
- Instrumenting your app this way gives you more control over exactly when the device starts and stops recording tracing information.
- 즉, CPU Profile 탭에서 start profiling을 클릭해서 프로파일링을 실행하는 것이 아니라, Debug 클래스를 사용하여 프로파일링을 실행할 수 있다. 이 방법을 사용하면 기기에서 recording traces의 시작/종료 시점을 더욱 정확하게 할 수 있다.
- 아래는 코드 라인에서 'sample.trace' 메서드 트레이스 파일을 생성 및 계측하는 코드이다.
- 프로파일링이 사용 설정된 경우 앱이 더 느리게 실행된다.
- 즉, 절대 메소드 실행 타이밍 ('foo() 메서드를 실행하는 데 2.5초가 걸림' 등) 을 판단하기 위해 프로파일링 데이터를 사용해서는 안 된다.
- 트레이스 로그의 타이밍 정보는 이전 트레이스 로그와 비교하는 경우에만 유용하므로 최근 변경으로 인해 앱이 더 빨라졌는지 또는 느려졌는지 확인할 수 있습니다.
- Android 5.0(API 수준 21) 이상을 실행하는 기기에 배포하는 경우 샘플 기반 프로파일링을 사용하여 런타임 성능에 미치는 영향을 최소화하면서 프로파일링할 수 있다.
- startMethodTracing() 을 호출하는 대신 지정된 샘플링 간격으로 startMethodTracingSampling() 을 호출합니다. 시스템은 앱이 stopMethodTracing() 을 호출할 때까지 주기적으로 샘플을 수집합니다.
여러 트레이스 로그 저장
- 앱에서 트레이스 로그에 새 이름을 지정하지 않고 메서드 트레이스를 여러 번 시작하고 중지하는 경우 기기에서 이전 트레이스 로그를 새 트레이스 로그로 덮어쓴다.
- 즉, 가장 최근의 트레이스 로그만 유지된다. 따라서 여러 트레이스 로그를 기기에 저장하려면 앱에서 startMethodTracing()을 호출할 때마다 동적으로 트레이스 로그의 이름을 바꿔야한다.
- 아래 샘플에서는 SimpleDateFormat 클래스를 사용하여 각 트레이스 로그의 이름을 현재 날짜와 시간으로 네이밍한다.
메모리 할당을 추적하는 프로파일러다.
메모리 프로파일러는 끊김 현상, 멈춤, 심지어 앱 비정상 종료로 이어질 수 있는 메모리 누수 및 메모리 변동을 식별한다. 앱의 메모리 사용 현황을 실시간 그래프로 보여주며, 메모리 프로파일러를 사용하여 힙 덤프를 캡처하고 가비지 컬렉션을 강제 실행하고 메모리 할당을 추적할 수 있습니다.
Android의 AOT는 메모리 환경을 관리한다. 앱에서 일부 객체를 더 이상 사용하지 않는다고 판단되면 AOT의 GC(Garbage Collector)가 사용되지 않는 메모리를 힙으로 돌려보낸다.
android VM의 GC를 주기적으로 릴리즈함으로써 unused memory를 찾는 방법은 끊임없이 개선되고 있지만, 모든 Android 버전에서 특정 시점(finding unused memory)에 시스템이 코드를 일시중지해야 한다. 대부분의 경우 이 일시중지를 감지할 순 없지만, 시스템에서 메모리를 수집할 수 있는 것보다 빠르게 앱에서 메모리를 할당하는 경우, 컬렉터가 충분한 메모리를 확보하는 동안 앱이 지연될 수 있다. 이로 인해 앱이 프레임을 skip하며 눈에 띄게 느려질 수 있다.
위의 경우가 아니더라도 메모리 누수(사용하지 않는 객체에 메모리 할당)가 발생할 경우 앱이 백그라운드에 있는 동안에도 메모리를 유지할 수 있다. 이 동작으로 인해 불필요한 가비지 컬렉션 이벤트가 강제로 실행되어 시스템의 나머지 메모리 성능이 저하될 수 있다. 결국 시스템에서 메모리를 확보하기 위해 앱 프로세스를 강제 종료해야 한다. 그러면 사용자가 앱으로 돌아올 때 앱을 완전히 다시 시작해야 한다.
위의 문제들을 방지하기 위해 Memory Profiler를 사용한다.
- Look for undesirable memory allocation patterns in the timeline that might be causing performance problems.
- Dump the Java heap to see which objects are using up memory at any given time. Several heap dumps over an extended period of time can help identify memory leaks.
- Record memory allocations during normal and extreme user interaction to identify exactly where your code is either allocating(할당) too many objects in a short time or allocating objects that become leaked(누수).
Memory Profiler
- button to force a garbage collection event
- button to capture a heap dump
- button to record memory allocations appears to the right of the heap dump button only when connected to a device running Android 7.1 (API level 25) or lower.
- dropdown menu to specify how frequently the profiler captures memory allocations
- Selecting the appropriate option may help you improve app performance while profiling.
- Buttons to zoom in/out of the timeline
- button to jump forward to the live memory data
- The event timeline, which shows the activity states, user input events, and screen rotation events
- The memory use timeline, which includes the following:
- A stacked graph of how much memory is being used by each memory category
- y-axis on the left : how much memory is being used by used memory
- y-axis on the right & dashed line : the number of allocated objects
- An icon for each garbage collection event.
How memory is counted
- Java
자바 또는 Kotlin 코드에서 할당된 객체의 메모리.
- Native
네이티브(C/C++) 코드에서 할당된 객체의 메모리.
- Even if you're not using C++ in your app, you might see some native memory used here because the Android framework uses native memory to handle various tasks on your behalf, such as when handling image assets and other graphics—even though the code you've written is in Java or Kotlin.
- Graphics
GL 표면, GL 텍스처 등 픽셀을 화면에 표시하기 위해 그래픽 버퍼 큐에 사용되는 메모리. (참고 : 이 메모리는 전용 GPU 메모리가 아니라 CPU와 공유된다)
- Stack
앱의 네이티브 및 자바 스택에서 사용하는 메모리. 일반적으로 앱에서 실행 중인 스레드 수와 관련이 있다.
- Code
앱에서 dex 바이트 코드, 최적화되거나 컴파일된 dex 코드, .so 라이브러리, 글꼴 등 코드 및 리소스에 사용하는 메모리.
- Others
앱에서 사용하는 메모리 중 시스템에서 분류하는 방법을 알지 못하는 메모리.
- Allocated
앱에서 할당한 자바/Kotlin 객체 수. C/C++에서 할당된 객체는 계산되지 않는다.
View memory allocations
- 타임라인을 드래그하여 할당을 확인할 영역을 선택하면 다음과 같은 정보들을 확인할 수 있다.
- 할당된 객체의 유형 및 할당된 객체가 사용하는 공간의 크기
- 각 할당의 스택 트레이스(할당이 들어 있는 스레드 포함)
- 객체가 할당 해제된 시점 (Android 8.0 이상을 실행하는 기기를 사용하는 경우에만)
- Android 8.0 이상
앱의 할당을 계속 추적하는 기기 내 프로파일링 도구가 포함되므로 기록 세션을 시작할 필요가 없다.
- Android 7.1 이하
툴바의 Record memory allocations - Stop recording 조작 필요
네트워크 프로파일러
네트워크 트래픽 사용량을 모니터링하는 프로파일러다.
네트워크 프로파일러는 타임라인에 실시간 네트워크 활동을 표시하여 송수신된 데이터 및 현재 연결 수를 보여준다. 이를 통해 앱에서 데이터를 전송하는 방법과 시기를 검토하고 기반 코드를 적절하게 최적화할 수 있습니다.
Network Profiler
- 이벤트 타임라인에서 트래픽을 검사할 부분을 클릭하고 드래그하여 선택할 수 있다.
- Connection View와 Thread View 중 하나를 선택하면 타임라인에서 해당 View의 네트워크 활동을 자세히 볼 수 있다.
- Connection View
앱의 모든 CPU 스레드에 걸쳐 타임라인의 선택된 부분 동안 전송되거나 수신된 파일이 나열됩니다. 각 요청의 크기, 유형, 상태 및 전송 기간을 검사할 수 있다. 헤더를 클릭하여 이 목록을 정렬할 수 있다. 각 파일이 전송되거나 수신된 시기를 보여주는, 타임라인의 선택된 부분에 관한 세부정보도 확인할 수 있다.
- Thread View
앱의 각 CPU 스레드의 네트워크 활동이 표시된다. Thread View를 사용하면 각 네트워크 요청을 담당하는 앱의 스레드를 검사할 수 있다.
- Connection View나 Thread View에서 요청 이름을 클릭하면 전송되거나 수신된 데이터에 관한 자세한 정보를 검사할 수 있다. 응답 헤더와 본문, 요청 헤더와 본문, 또는 호출 스택을 보려면 탭을 클릭하면 된다.
- Response 및 Request 탭에서 View Parsed 링크를 클릭하면 서식이 지정된 텍스트가 표시되고 View Source 링크를 클릭하면 원시 텍스트가 표시된다.
에너지 프로파일러
배터리 소진에 영향을 미치는 에너지 사용을 추적하는 프로파일러