Hanbit the Developer

Android Document | App startup time 본문

Mobile/Android

Android Document | App startup time

hanbikan 2024. 1. 25. 01:42

The different app startup states

앱을 처음부터 시작하는 cold start를 기준으로 최적화하는 것이 권장된다.

최적화 지표를 위한 지표는 다음과 같다:

  • TTID: time to initial display
  • TTFD: time to fully drawn

Cold start

앱이 처음부터 시작하는 것을 의미한다. 기기 부팅된 뒤 앱이 처음으로 시작될 때, 앱이 시스템으로부터 종료된 후 앱이 시작될 때 콜드 스타트가 발생한다.

소요 시간이 가장 긴 유형이다.

콜드 스타트 초기에 시스템은 다음과 같은 작업을 수행한다:

  1. 앱 로드 및 시작
  2. 앱 시작 후 곧바로 blank starting window 띄움
  3. 앱 프로세스 생성

앱 프로세스가 생성되면 프로세스는 다음과 같은 작업을 수행한다:

  1. app object생성
  2. 메인 쓰레드 실행
  3. 메인 액티비티 생성
  4. Inflate views
  5. Layout the screen
  6. initial draw 수행

프로세스가 처음으로 화면을 그리고 나면, 시스템 프로세스는 기존에 보여지던 window를 메인 액티비티로 교체한다. 이때부터 사용자는 앱을 사용할 수 있다.

성능 이슈는 앱과 액티비티 생성 부분에서 발생할 수 있다.

Warm start

웜 스타트는 콜드 스타트의 작업 일부를 포함하며 핫 스타트보다 오버헤드가 높다. 다음과 같은 경우 웜 스타트로 간주될 수 있다:

  • 사용자가 앱을 종료한 뒤 다시 시작하는 경우. 프로세스는 계속해서 실행되고 있을 순 있지만 앱은 onCreate()를 통해 액티비티를 처음부터 재생성해야 한다.
  • 시스템이 앱을 메모리에서 제거한 뒤 사용자가 앱을 다시 시작하는 경우. 프로세스와 액티비티 모두 재시작되어야 하지만, onCreate()로 전달된 saved instance state 번들을 통해 이득을 볼 수 있다.

Hot start

핫 스타트는 콜드 스타트보다 오버헤드가 낮다. 핫 스타트에선 시스템이 액티비티를 포어그라운드로 가져온다. 모든 액티비티가 여전히 메모리에 있으면 객체 초기화, layout inflation, 랜더링을 다시 하지 않아도 된다.

하지만 메모리 일부가 onTrimMemory() 같은 memory trimming 이벤트로 삭제된 경우에는 일부 객체들이 재생성되어야 한다.

콜드 스타트와 같이, 액티비티 랜더링을 마치기 전까지 빈 화면을 디스플레이한다.

How to identify app startup in Perfetto

https://developer.android.com/topic/performance/vitals/launch-time#app-startup-perfetto

Use metrics to detect and diagnose problems

https://developer.android.com/topic/performance/vitals/launch-time#ddp

Solve common issues

Heavy app initialization

Application을 오버라이드 해서 객체를 초기화할 때 많은 작업을 하게 되면 퍼포먼스가 문제가 발생할 수 있다.

다음과 같은 코드를 주의한다:

  • onCreate()
  • 앱이 초기화하는 글로벌 싱글톤 객체
  • 병목 시 발생할 수 있는 Disk I/O, deserialization, tight loops

솔루션은 다음과 같다:

  • 필수적인 것만 초기화하고 lazily initialize하기
  • global static object를 생성하지 말고, 처음으로 필요할 때 초기화되는 싱글톤 패턴 사용하기(Hilt의 장점 중 하나임)
  • 시작 시 content provider를 사용하는 경우 App Startup library 사용하기

Heavy activity initialization

액티비티 생성 시 오버헤드가 큰 경우 퍼포먼스 이슈가 발생한다. 다음과 같은 곳에서 문제가 발생할 수 있다:

  • 크거나 복잡한 레이아웃 inflating
  • Disk, network I/O 도중에 화면 drawing 차단
  • 비트맵 로드 및 디코딩
  • VectorDrawable 객체 레스터화
  • 액티비티의 다른 서브시스템 초기화

다음과 같은 코드를 주의한다:

  • onCreate()
  • 액티비티가 초기화하는 글로벌 싱글톤 객체
  • 병목 시 발생할 수 있는 Disk I/O, deserialization, tight loops

솔루션은 다음과 같다:

  • 뷰 관련
    • 뷰 계층구조 줄이기(중복 제거, Constraint Layout 사용 등)
    • 시작 시간에 보이지 않는 뷰를 inflate 하는 대신, ViewStub를 placeholder로서 사용하고 적절할 때 inflate 하기
  • 리소스 초기화를 모두 메인 쓰레드에서 하는 것은 적절하지 않다:
    • 앱이 리소스 초기화를 lazily하게 다른 쓰레드에서 처리하게 하기
    • 앱이 뷰를 로드하고 디스플레이 한 뒤에, 비트맵 등 리소스에 의존하는 뷰 업데이트 하기

Custom splash screens

아래처럼 Android 11 및 이전 버전에서 커스텀 스플래시를 구현한 경우 앱 시작이 지연될 수 있다:

  • windowDisablePreview 속성으로 시스템이 처음에 그리는 빈 화면을 제거한 경우
  • 전용 Activity를 사용한 경우

Android 12 버전부터 SplashScreen API로 마이그레이션 해야 한다. 해당 API로 시작 시간을 개선하고 다음과 같이 스플래시를 변형할 수 있다:

문서 링크

https://developer.android.com/topic/performance/vitals/launch-time

'Mobile > Android' 카테고리의 다른 글

UI State Flow 이슈 해결  (0) 2024.01.25
Android Document | Processes and app lifecycle  (3) 2024.01.25
Room Migration 방법  (0) 2024.01.17
ViewModelStore, ViewModelProvider 분석  (1) 2024.01.12
AnimatedVisibility 오버랩 이슈 해결  (1) 2024.01.11