안드로이드 UI 최적화 업적을 달성해보자는 목표로 프로파일링을 시작했다. UI 최적화는 UI의 버벅이는 현상, UI jank를 최소화하는 것이다.
프로파일링 범위는 '소셜로그인 후 메인 홈 진입' 부분이다.
이전 포스팅에서는 프로파일링이 이런거구나 살짝 발을 담궈보았다.
이 포스팅에서는 UI 속도가 느려지는 이유를 밝히는데 유용한 지표와 개념을 정리했다. 또한 그 지표를 바탕으로 UI버벅임 현상을 해석하고, 앞으로의 최적화 방향성을 생각해보았다.
이 포스팅은 추가적인 분석과 해석 수정이 들어갈 여지가 많고, 더 내용이 발전될 것 같다.😀
안드로이드 프로파일링 툴 공식문서를 찾아보면 특히 Detect UI jank에 관련한 중요 지표들이 나온다. 바로 Frames, SurfaceFlinger, VSYNC, BufferQueue이다.
애플리케이션의 UI스레드와 RenderThread에서 발생하는 이벤트를 보여주는데, 각 이벤트는 해당 프레임이 처리되는 데 걸린 시간이다.
프레임 렌더링은 16ms 이상 걸리면 빨간색이 된다. 16ms 이상 걸린다는 뜻은 애플리케이션 권장 속도인 60fps에 미치지 못한다는 안 좋은 뜻이다.
아래의 캡처화면에서 빨간색으로 표시된 부분이 UI jank의 주요원인이될 수 있는 구간이다.
눈에 띄는 구간만 해도 1.22s, 1.8s, 2.27s 로 최소 5.29초 버벅인다는 뜻이다.
5초 이상 버벅인다고 느꼈던 게 정말 맞았다는 걸 확인할 수 있었다.
SurfaceFlinger는 안드로이드 시스템 프로세스로, 애플리케이션에서 생성된 버퍼를 디스플레이로 전송하는 역할을 한다.
안드로이드 공식문서의 그래픽 데이터 흐름을 보면 아래와 같이 되어있는데, 익숙한 BufferQueue를 중심으로 생각했을 때 surfaceFlinger는 이미지 스트림 소비자인 것이다.
아무튼!surfaceFlinger 프로세스가 프레임 버퍼를 처리하는 시점도 프로파일링에 유용한 지표이다.
더 확대한 부분은 소셜 로그인 중에 처리된 프레임 버퍼인데, BufferQueue에 프레임이 쌓인 후 거의 바로 처리되어서 surfaceFlinger에 뿅하고 지표 상 짧게나타났다.
소셜 로그인, 로딩, 메인 화면 모두 BufferQueue에 쌓인 후 바로 처리되는 것으로 보아 일단 이미지 프레임 소비는 빠르게 이루어졌다.👍
이 섹션은 VSYNC 신호를 표시하며, 화면 출력과 동기화되는 신호이다. VSYNC는 UI스레드가 작업을 너무 늦게 시작할 때 표시되기 때문에 UI 스레드가 바쁜 정도로 해석할 수 있는 지표이다. UI 스레드가 바쁘면 애니메이션 도중 화면 깜빡임이 발생할 수 있다.
로그인 후 메인 화면에 진입하고나서 화면 깜빡임이나 속도가 느린게 느껴졌기 때문에 자세히 본 결과 확실히 VSYNC 신호 빈도가 높은 것도 확인할 수 있었다.
신호의 폭이 다양하지만 최소 72ms, 평균 165ms마다 UI스레드가 작업을 늦게 시작한다는 것을 확인할 수 있었다. 메인 화면이 시작되고 컨텐츠를 로딩하는 1.2초 동안 버벅임이 8번 정도 있었다고 해석했다.이걸 어느 정도 개선할 수 있는지 궁금해진다.🤔
BufferQueue는 SurfaceFlinger가 사용할 수 있도록 준비된 프레임 버퍼이다.
Android 9(API level 28) 이상에서는 애플리케이션의 BufferQueue 버퍼 개수를 표시하는데, 이 프로파일링에 API 28의 기기가 사용되었기 때문에 주로 0,1,2의 값으로 표시된다. 값이 2일 때는 애플리케이션이 삼중 버퍼링 상태에 있음을 의미하며, 추가적인 입력 지연이 발생할 수 있다는 뜻이다.
메인화면 구간에서의 BufferQueue 값들을 모두 확인한 결과 1이었다. 대기했다가 거의 바로 처리되었다는 뜻이다. 다른 구간에서도 모두 BufferQueue 버퍼 개수의 최대치는 1으로, 버퍼링 문제는 없다고 해석했다.
Frames, SurfaceFlinger, VSYNC, BufferQueue 지표를 살펴본 결과 SurfaceFlinger, BufferQueue와 관련된 버퍼링 문제는 없었다.
Frames 처리시간이 길고, VSYNC 신호 빈도가 높은 것이 두드러진다고 생각한다.
지표를 해석해보니까 이제야 프로파일링 com.hmoa.app Threads의 작업들 중에서 Recompose, Compose, measure 작업이 많은 것이 눈에 들어온다.
결국 화면을 렌더링하는데 있어서 불필요한 깜박임과 드로잉 시간이 있다. 즉 불필요한 컴포지션이 많으니, 컴포지션 코드 최적화를 해야한다는 뜻인 것 같다. 프로젝트 개발을 진행하면서 1.0.0 버전을 출시하고 중요한 버그 및 추가 서비스 출시가 어느 정도 되면 컴포지션 최적화를 해야겠다고 생각은 했었다. 하지만 컴포지션 최적화를 하지 않았을 때 정량적으로 어떤 문제가 있고, 컴포지션 최적화를 해야하는 정확한 근거를 마련해본 적은 없었던 것 같다.
위의 스크린 샷의 Threads에 표시된 스크린들을 위주로 컴포지션 최적화를 한 후, 다시 프로파일링 하며 개선결과를 업데이트 해봐야겠다.