리눅스 기반의 프로세스 성능 분석의 경험은 있으나 안드로이드 어플리케이션의 성능 분석은 처음이다. 학생 이후에 약 10년 만에 안드로이드 개발을 해보는 상황으로 도메인 지식이 많이 부족하다. 안드로이드 플랫폼에서 어떤 프로파일링 툴을 제공하고 어떻게 사용해야 하는지 파악을 해보고 싶었고, 문제를 좀 더 빠르게 분석하고자 했다.
현재 안드로이드 웨어OS 기반의 헬스 어플리케이션을 개발하고 있다. 디바이스 타겟은 갤럭시 워치 4이며 헬스 기능은 안드로이드에서 제공하는 헬스 API를 사용한다 .(Samsung Health는 파트너 체결 등의 이유로 사용하지 않았다.)
처음 서비스 로드가 너무 느려!
문제는 디바이스 부팅 후 첫 헬스 서비스 사용 시 시스템에서 헬스서비스의 로드가 매우 느리다는 문제가 있었다. 처음 로드된 이후에는 재사용 시에도 빠르게 동작함을 확인할 수 있다.
어플리케이션 내의 헬스서비스매니저의 과도한 CPU 점유
HealthServiceManager의 Client 오브젝트를 이용해 Health를 시작하는 구간이다. 시작버튼을 이용하여 운동 시작 시 아래 그림과 같이 어플리케이션의 메인 스레드는 CPU를 점유해서 동작하는 부분이 존재하지 않는다. 빨간색 화살표가 운동 시작 버튼 이벤트 발생 시점이다. 그 이후 SurfaceFlinger에서도 별도로 디스플레이에 그리기 위한 버퍼 작업을 하지 않고 있다. 어디선가 CPU가 점유되고 다른 작업을 하고 있는 경우로 보인다.
아래로 찾아보니, HsConnectionMan(HealthServiceConnectionManager 의 약자로 추정) 스레드가 Core2를 점유하면서 작업을 하고 있다. 그 이후에 표시된 부분은 운동 종료 버튼을 누린 것이다. 시작버튼 - 종료버튼 이벤트 발생 사이에 HsConnectionMan 스레드의 CPU 코어 점유가 상승하고, 중간 쯤 어플리케이션이 다시 디스플레이에 Drawing을 하는 것을 알 수 있다. 즉 운동서비스 연결이 완료 된 이후 데이터를 서비스로부터 받아 화면에 표시하기 시작한 것이다.
Perfetto를 이용한 추가 분석
안드로이드 스튜디오의 CPU 프로파일링 기능만으로는 정보가 부족하여 Perfetto(https://perfetto.dev/) 를 이용하여 systrace 데이터를 분석해 보려 하였다. 운동 시작 버튼 이벤트 발생 후 HsConnectMan 스레드는 core를 점유하고 Running 상태가 지속되고 있다.
중간에 binder가 다른 서비스와 바인딩 되는 것으로 보인다. 바인딩 되는 서비스를 확인하니 com.google.android.wearable.healthservices 이다. 바인딩 이후 바인딩 완료에 대한 응답을 보내서 처리하도록 한다. 하지만 예상보다 오래 걸리는 부분은 없다.
HsConnectionMan 스레드에서 전 처리 이후 healthservices 스레드와 바인딩하고 처리를 한다. 어떤 처리를 하는지에 대해서 까지는 해당 툴로는 파악이 힘들었다. 디바이스 IO 또는 메모리 쪽 문제를 확인하기 앞서 Call Stack 정보를 확인해보려 하였지만, core 수가 적은 갤럭시 워치 4는 Call Stack 정보를 파싱해오기에 어려움이 있었다. 발열로 인해 기기가 정상적으로 동작하지 않았으며, Call Stack 정보는 깨져서 확인이 힘들었다. CPU 부하가 큰 상황에서 Call Stack 분석은 어려움은 알고 있었기에 큰 기대는 없었지만, 샘플링 타임이라도 변경하는 기능이 있으면 좋으련만 그런 기능은 제공하지 않는다.
결론
뭔가 시원하게 해결되지는 않았다. 생각보다 제약사항이 많았고, 안드로이스 프레임워크의 이해가 부족했다. HealthService가 아니라 어플리케이션 동작 자체의 문제가 있는지 확인이 필요할 것 같다.
'Android > Component' 카테고리의 다른 글
ViewModel의 DataEvent 처리 방법 #1. LiveData (0) | 2022.10.13 |
---|---|
[Android] 하단 탭 사용하기 (BottomNavigation) (0) | 2022.08.31 |
[Android] Google Map Key 관리 (0) | 2022.08.16 |
[Android] local.properties를 사용하여 키 관리하기 (2) | 2022.08.08 |
[Android] 위치(Location) (1) | 2022.07.14 |