brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Feb 03. 2017

안드로이드 개발자 옵션 렌더링 #02

프로필 GPU 렌더링, 렌더링 비용 줄이기

1. 프로필 GPU 렌더링


프로필 GPU 렌더링 툴은 앱이 느려질 경우 어디서 문제가 생겼나 보여주는, 개발자 옵션에 포함된 기능입니다.





#01 프로필 GPU 렌더링

프로필 GPU 렌더링을 실행하면 현재 활성화된 앱의 렌더링 시간을 수직 막대 형태로 보여줍니다.

각 수직 막대는 한 프레임인데, 높이가 높을수록 렌더링 시간이 오래 걸렸다는 뜻입니다.


더 많은 프레임이 렌더링 되면 바가 연속으로 나오는데, 시간당 프레임 속도를 보시는 겁니다.


녹색 라인은 16 밀리세컨드를 나타내는데요.

초당 60 프레임이 되려면 각 수직 막대가 16ms 라인에 닿지 않도록 하면 됩니다.

막대가 이 라인 위로 튀어나오면 해당 프레임이 드랍되어 앱이 느려진 것처럼 보이게 됩니다.






초당 60 프레임

#02 Praxinoscope

초당 60 프레임은 인체 구조 상 정해진 숫자입니다.

사실 정적인 프레임으로 동작을 보여주는 것은 착시현상인데, 이미지를 연속해서 빠르게 보여주면 뇌는 그걸 동작이라고 잘못 인식해버리는 겁니다.

여기서 중요한 건, 연속해서 보여주는 속도가 그 동작이 얼마나 매끄러운가를 결정한다는 거죠.

초당 60 프레임이 착시현상 없이도 매끄러운 동작의 핵심인 겁니다

(60 프레임 이상은 사람이 구분하기 어려우니 큰 의미가 없다고 하네요).


그런데 프레임을 보여주는 중에 속도의 가감이 있다면 인체의 눈 구조상 바로 보이게 되어 있습니다.

예를 들면, 60 프레임으로 잘 가다가 가끔씩 갑자기 30 프레임으로 드랍할 때, 눈은 바로 문제를 느낍니다.

이 순간 앱이 느려졌다고 느껴지게 됩니다.


결론은 유저가 앱을 쓰는 중에는 항상 초당 60 프레임 유지!

1000ms / 60 frames = 16.666ms / frame

즉 16ms 안에 한 프레임을 그리는 작업을 다 해야 합니다.




렌더링 스테이지

#03 프로필 GPU 렌더링 Color



Swap Buffers

CPU가 GPU가 작업을 마칠 때까지 기다리는 시간을 나타냅니다. 

앱이 GPU에서 너무 많은 작업을 하고 있음을 의미합니다
(GPU에 복잡한 뷰 작업이 많이 들어가서 오픈 GL 렌더링 명령어가 많이 필요하다는 의미).

Command Issue

안드로이드의 2D 렌더러에서 디스플레이 리스트를 화면에 그리는 데 필요한 모든 명령을 실행하는 데 걸리는 시간을 나타냅니다

(OpenGL에 명령을 보내 디스플레이 목록을 그리고 다시 그리는 데 소비 한 시간을 나타냅니다). 

복잡한 뷰이거나 대량의 뷰를 다시 그리라는 확률이 높습니다.

Sync & Upload

Bitmap 정보를 GPU로 업로드하는 데 걸리는 시간을 나타냅니다.

앱이 많은 양의 그래픽을 로드하는 데 시간이 오래 걸린다는 것을 나타냅니다.

Draw

뷰의 표시 목록을 만들고 업데이트하는 데 사용된 시간을 나타냅니다.

onDraw 메서드에서 복잡하거나 많은 양의 커스텀뷰 작업이 있을 수 있습니다.

Measure / Layout

뷰 계층에서 onLayout 및 onMeasure 콜백에 소요된 시간을 나타냅니다.

뷰 계층 구조가 처리하는 데 오랜 시간이 걸린다는 것을 나타냅니다.

Animation

해당 프레임을 실행 중인 모든 애니메이터를 평가하는 데 걸린 시간을 나타냅니다.

앱이 퍼포먼스가 좋지 않은 커스텀 애니메이터를 사용하고 있거나 속성 변경으로 의도하지 않은 작업이 진행되고 있을 수 있습니다.

Input Handling

앱이 입력 이벤트 콜백 내부에서 코드를 실행하는 데 사용한 시간을 나타냅니다.

앱이 사용자 입력을 처리하는 데 너무 많은 시간을 소비하고 있음을 나타냅니다.
이러한 처리를 다른 스레드로 처리하기 권장합니다.

Misc Time / VSync Delay

렌더링 시스템이 작업을 수행하는 데 걸리는 시간 외에도, 메인 스레드에서 발생하고 렌더링과 관련이 없는 추가 작업 세트가 있습니다. 이 작업이 소비하는 시간은 기타 시간으로 부르는데 일반적으로 렌더링의 두 연속 프레임 사이에서 UI 스레드에서 발생할 수 있는 작업을 나타냅니다.

UI 스레드에서 너무 많은 처리가 발생하는 것을 나타냅니다.




Android 6.0 이하 버전에서는 위와 다르게 4가지 색상(주황, 빨강, 보라, 파랑) 색으로 표시됩니다.

자세한 내용은 아래 내용을 참조해주세요.

https://developer.android.com/studio/profile/dev-options-rendering.html




https://developer.android.com/topic/performance/rendering/profile-gpu.html##visrep


2. 렌더링 비용 줄이기


Command Issue

복잡한 뷰이거나 대량의 뷰를 다시 그리라는 확률이 높습니다.

아래와 같이 같은 결과물이지만 로직만으로 draw 명령을 GPU로 보내는데 걸리는 시간을 줄일 수 있습니다.

// expensive 
for (int i = 0; i < 1000; i++)
canvas.drawPoint()
// cheap
canvas.drawPoints(mThousandPointArray);

Sync & Upload

앱이 많은 양의 그래픽을 로드하는 데 시간이 오래 걸린다는 것을 나타냅니다.

Bitmap 해상도가 표시되는 크기보다 훨씬 크지 않은지 확인해야 합니다.

예를 들어, 1024x1024 이미지를 48x48 이미지로 표시하지 않아야 합니다.

Bitmap을 비동기 적으로 미리 업로드하려면 prepareToDraw ()를 사용합니다.


Input Handling

앱이 사용자 입력을 처리하는 데 너무 많은 시간을 소비하고 있음을 나타냅니다.
이러한 처리를 다른 스레드로 처리하기 권장합니다.

작업을 최적화하거나 작업을 다른 스레드에서 처리하도록 수정해야 합니다.





개발을 하다 보면 여러 이유들로 인해 렌더링 문제가 발생하기 쉽고, 그만큼 발견하기도 많이 쉬워졌습니다.

하지만 이를 개선하기는 쉽지가 않네요ㅠ


기본적인 레이아웃 개선에서부터 GPU 레벨까지, 파악해서 커스텀뷰 개선까지 너무 방대하다 보니

구글에서도 정확히 어디 어디를 개선하라가 아닌, 여러 가지 툴을 이용해서 최적화하라는 추상적인 해결책을 제시하고 있습니다.


안드로이드에서는 프로필 GPU 렌더링 외에도 아래와 같은 툴들을 제공하고 있습니다.

렌더링 이슈를 해결하는데 도움이 되시길 바랍니다.

프로필 GPU 렌더링

https://developer.android.com/studio/profile/traceview.html

https://developer.android.com/studio/profile/systrace.html


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari