사용자는 앱이 빠르게 로드되길 바라는데 시작 시간이 느리면 구글 플레이 스토어에서 낮은 점수를 받을 수도 있고,,
앱을 아예 사용안할 수도 있으니 앱 시작 시간을 최적화하는데 도움을 주겠다는 내용이다.
1. Understand app-start internals
- 앱은 Cold start, Warm start, Hot start 라는 3가지 상태 중에서 시작한다
- 위의 각 상태는 사용자에게 앱이 로드되는데 걸리는 시간에 영향을 준다
- Cold start 는 앱이 처음부터 시작, 이 외는 실행중인 앱을 background -> foreground 로 가져와서 시작
- 그러니 항상 Cold start 를 기준으로 최적화를 해보자! 그럼 자연히 다른 시작 상태의 성능도 개선될 것이다!
2. Cold start
- 앱이 처음부터 시작하는 것
- 시스템 프로세스는 Cold start 전에는 앱의 프로세스를 만들지 않는다
- ex) 기기 부팅, 시스템에서 앱 종료 후 처음 시작하는 경우 등
처음 시작하는거니 다른 시작 상태보다 더 많은 작업을 실행한다.
- 앱 로드 및 시작
- 시작 직후 앱의 빈 화면 표시
- 앱 프로세스 생성
3번 앱 프로세스가 생성되면 아래 단계를 실행한다.
- 앱 객체 생성
- 메인 스레드 시작
- 메인 액티비티 생성
- 뷰 붙이기
- 레이아웃 배치
- 초기 그리기 실행
6번이 완료되면 시스템 프로세스에서 현재 표시된 백그라운드 화면을 메인 액티비티로 교체하면 본격적으로 앱을 사용할 수 있다.
여기서 앱을 만들고 액티비티를 생성하는 동안 성능 문제가 발생할 수 있다.
2-1. Application creation
- 어플리케이션이 시작되면 시스템에서 처음 앱을 그리는게 완료될 때까지 빈 시작 화면이 남아있다
- 위 시점에 Application.onCreate() 가 오버로드되면 시스템이 앱 객체에서 onCreate() 메서드를 호출한다
- 이 후 메인 스레드인 UI 스레드를 생성하고 메인 액티비티를 생성한다
- 여기서부터 Processes and Application Lifecycle 에 따라 진행된다
2-2. Activity creation
- 앱 프로세스에서 액티비티를 만든 후 아래 작업을 실행한다.
- 값 초기화
- 생성자 호출
- Activity lifecycle 메서드 호출
- 여기서 뷰 로딩 & 확장, 필요한 객체를 초기화하는 onCreate() 메서드의 오버헤드가 가장 높다
3. Hot start
- Cold start > Hot start : 훨씬 더 간단하고 오버헤드 낮다
- 시스템이 액티비티를 foreground 로만 가져오면 된다
- 어플리케이션의 모든 액티비티가 메모리에 남아있으면 객체 초기화, 레이아웃 확장, 렌더링 등을 안해도 된다
- 하지만 메모리에서 삭제된 경우 객체를 다시 만드는 대응을 해야한다
4. Warm start
- Cold start > Warm start > Hot start : Cold start 작업의 하위 집합을 포함해서 Hot start 보다는 오버헤드가 높다
- ex1) 사용자가 앱 종료 후 재시작하여 앱이 onCreate() 부터 액티비티를 다시 만들어야하는 경우
- ex2) 시스템이 메모리에서 앱을 제거 후 사용자가 앱 재시작 : onCreate() 에 전달된 savedInstanceState 있는 경우
5. Detect and diagnose problems
5-1. Anroid vitals
Google Play Console 의 Android vitals 에서 데이터 확인 가능하며, 아래와 같은 경우 앱 시작 시간이 긴걸로 간주한다.
(Android vitals 는 Hot start 의 데이터는 보고하지 않는다.)
- Cold start : 5초 이상
- Warm start : 2초 이상
- Hot start : 1.5초 이상
5-2. Diagnosing slow startup times
AndroidStudio 의 logcat 에 Displayed 라는 값이 포함된 내용이 있는데, 이게 바로 프로세스 시작 후 액티비티를 화면에 그릴 때까지 소요된 시간을 나타낸다. 앱 자체가 아니라 시스템 서버에서 로그를 제공하므로 No Filters 로 설정하고 봐야한다.
- 프로세스 시작
- 객체 초기화
- 액티비티 생성하고 초기화
- 레이아웃 확장
- 어플리케이션 그리기
ActivityTaskManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
아래 경우 total 시간은 앱 프로세스가 시작하고 화면에 아무것도 표시하지 않은 것도 포함한걸로 단일 액티비티와 총 시작 시간 사이 차이가 있을때만 표시된다.
ActivityTaskManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
ADB Shell 로 앱 실행부터 메인 액티비티를 표시까지 걸린 시간을 측정할 수도 있다.
shell am start -S -W
또한 병목 현상을 찾으려면 AndroidStudio CPU Profiler 를 사용해보면 된다. 이 외 시간 측정은 Time to full display 참고
6. Be aware of common issues
시작 시간을 줄이기 위해 아래와 같은 문제를 진단 후 해결해보자 (문서 참고)
- 과도한 앱 초기화 : onCreate(), 전역 싱글턴 객체, 디스크 I/O, 역직렬화 등
- 과도한 액티비티 초기화 : 크고 복잡한 레이아웃 확장, 디스크/네트워크 I/0 시 UI 그리기 차단, 비트맵 로딩,VectorDrawable 객체 래스터 등
'Android개발' 카테고리의 다른 글
Migrating build.gradle from Groovy to Kotlin (0) | 2020.09.25 |
---|---|
Android Lint #2 - Custom Lint (0) | 2020.07.03 |
Android Lint #1 - 기본 (0) | 2020.07.02 |
App Startup (0) | 2020.06.25 |
Elevation (0) | 2020.03.18 |
댓글