안드로이드 시스템·Compose 용어 사전
성능AOT · Macrobenchmark · 잰크

Baseline Profile

핵심 경로를 미리 AOT 컴파일하도록 알려 주는 프로필. 시작 시간을 크게 줄인다.

핵심 경로를 미리 AOT 컴파일하도록 알려 주는 프로필.

왜 첫 실행이 느린가

ART 는 기본적으로 인터프리터로 시작하고, 자주 도는 코드만 JIT 으로 컴파일한다 → 첫 실행은 느리다

Baseline Profile 을 함께 배포하면

  • 설치 시점에 그 목록의 메서드를 AOT 컴파일해 둔다
  • 첫 실행부터 컴파일된 코드로 돈다

공식 수치로 시작 시간 약 30% 개선 사례가 보고된다

// baselineProfile 모듈에서 시나리오를 적으면 프로필이 생성된다
@Test fun generate() = baselineProfileRule.collect(packageName = "com.example") {
    startActivityAndWait()
    device.findObject(By.res("feed")).fling(Direction.DOWN)   // 자주 쓰는 경로를 훑는다
}

결과가 src/main/baseline-prof.txt 로 들어가고 AAB 에 함께 담겨 배포된다

시작 시간의 세 종류

  • cold — 프로세스가 없는 상태에서 시작. 가장 느리고 가장 중요하다

  • warm — 프로세스는 살아 있고 Activity 만 다시 만든다

  • hot — 화면만 다시 앞으로 가져온다

  • Play Console 이 보는 것도 cold 시작이다

시작을 늦추는 흔한 원인

  • Application.onCreate 에서 SDK 를 전부 초기화한다
    • androidx.startup 으로 지연 초기화하거나 필요 시점으로 미룬다
  • 메인 스레드에서 SharedPreferences · DB 를 읽는다
  • 스플래시를 직접 구현해 화면을 두 번 만든다
    • SplashScreen API 를 쓴다
  • 첫 화면에서 큰 이미지를 디코딩한다

측정한다 — 추측하지 않는다

@Test fun startup() = benchmarkRule.measureRepeated(
    packageName = "com.example",
    metrics = listOf(StartupTimingMetric()),
    iterations = 10,
    startupMode = StartupMode.COLD
) { pressHome(); startActivityAndWait() }
도구 선택
  Macrobenchmark   시작 시간 · 스크롤 잰크 (실제 앱을 띄워 측정)
  Microbenchmark   함수 단위 성능
  Perfetto / 시스템 추적  프레임 단위로 무엇이 오래 걸렸는지
  Android Studio 프로파일러  CPU · 메모리 · 네트워크

반드시 릴리스 빌드로 측정한다 — 디버그 수치는 의미가 없다

면접 함정

  • "Baseline Profile은 코드를 바꾼다" → 컴파일 대상 목록일 뿐이다. 동작은 그대로다.
  • "프로필을 한 번 만들면 끝" → 코드가 바뀌면 낡는다. CI에서 주기적으로 재생성한다.

Startup Profile도 있다

  • Baseline Profile — 무엇을 AOT 컴파일할지
  • Startup Profile — DEX 안에서 클래스를 어떤 순서로 배치할지

시작 시 읽는 클래스를 앞쪽에 모으면 페이지 폴트가 줄어든다 둘 다 같은 도구로 함께 생성된다

스플래시를 직접 만들지 않는다

// 시스템 SplashScreen API
installSplashScreen().setKeepOnScreenCondition { viewModel.isLoading }

직접 SplashActivity 를 만들면

  • Activity 를 두 번 만들고, 테마 전환이 깜빡이고, 시작이 오히려 늦어진다

setKeepOnScreenCondition 은 남용하면 시작이 느려 보인다 — "정말 없으면 화면을 못 그리는 것" 만 기다린다

초기화를 미룬다

// androidx.startup — 초기화 순서를 선언하고 지연시킨다
class AnalyticsInitializer : Initializer<Analytics> {
    override fun create(ctx: Context) = Analytics.init(ctx)
    override fun dependencies() = emptyList<Class<out Initializer<*>>>()
}

Application.onCreate 에 SDK 를 열 개 넣으면 그 합이 곧 시작 시간이다

  • 첫 화면에 필요 없는 것은 전부 미룬다 (by lazy · 화면 진입 시)
  • 광고·분석 SDK 가 특히 무겁다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 메모리·ANR·성능 — 누수·프리징·렉