본문으로 건너뛰기
cccskills
무료GitHub에 공개

compose-performance-audit

Audit and improve Jetpack Compose runtime performance from code review and architecture. Use when asked to diagnose slow rendering, janky scrolling, excessive recompositions, or performance issues in Compose UI.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(1)

  • SKILL.md6.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Compose Performance Audit

Overview

Audit Jetpack Compose view performance end-to-end, from instrumentation and baselining to root-cause analysis and concrete remediation steps.

Workflow Decision Tree

  • If the user provides code, start with "Code-First Review."
  • If the user only describes symptoms, ask for minimal code/context, then do "Code-First Review."
  • If code review is inconclusive, go to "Guide the User to Profile" and ask for Layout Inspector output or Perfetto traces.

1. Code-First Review

Collect:

  • Target Composable code.
  • Data flow: state, remember, derived state, ViewModel connections.
  • Symptoms and reproduction steps.

Focus on:

  • Recomposition storms from unstable parameters or broad state changes.
  • Unstable keys in LazyColumn/LazyRow (key churn, missing keys).
  • Heavy work in composition (formatting, sorting, filtering, object allocation).
  • Unnecessary recompositions (missing remember, unstable classes, lambdas).
  • Large images without proper sizing or async loading.
  • Layout thrash (deep nesting, intrinsic measurements, SubcomposeLayout misuse).

Provide:

  • Likely root causes with code references.
  • Suggested fixes and refactors.
  • If needed, a minimal repro or instrumentation suggestion.

2. Guide the User to Profile

Explain how to collect data:

  • Use Layout Inspector in Android Studio to see recomposition counts.
  • Enable Recomposition Highlights in Compose tooling.
  • Use Perfetto or System Trace for frame timing analysis.
  • Check Macrobenchmark results for startup/scroll metrics.

Ask for:

  • Layout Inspector screenshot showing recomposition counts.
  • Perfetto trace or System Trace export.
  • Device/OS/build configuration (debug vs release).

Important: Ensure profiling is done on a release build with R8 enabled. Debug builds have significant overhead.

3. Analyze and Diagnose

Prioritize likely Compose culprits:

  • Recomposition storms from unstable parameters or broad state changes.
  • Unstable keys in lazy lists (key churn, index-based keys).
  • Heavy work in composition (formatting, sorting, object allocation).
  • Missing remember causing recreations on every recomposition.
  • Large images without Modifier.size() constraints.
  • Unnecessary state reads in wrong composition phases.

Summarize findings with evidence from traces/Layout Inspector.

4. Remediate

Apply targeted fixes:

  • Stabilize parameters: Use @Stable or @Immutable annotations on data classes.
  • Stabilize keys: Use stable, unique IDs for LazyColumn/LazyRow items.
  • Defer state reads: Use derivedStateOf, lambda-based modifiers, or Modifier.drawBehind.
  • Remember expensive computations: Wrap in remember { } or remember(key) { }.
  • Skip recomposition: Extract stable composables, use key() to control identity.
  • Async image loading: Use Coil/Glide with proper sizing constraints.
  • Reduce layout complexity: Flatten hierarchies, avoid deep nesting.

Common Code Smells (and Fixes)

Unstable lambda captures

// BAD: New lambda instance every recomposition
Button(onClick = { viewModel.doSomething(item) }) { ... }

// GOOD: Use remember or method reference
val onClick = remember(item) { { viewModel.doSomething(item) } }
Button(onClick = onClick) { ... }

Expensive work in composition

// BAD: Sorting on every recomposition
@Composable
fun ItemList(items: List<Item>) {
    val sorted = items.sortedBy { it.name } // Runs every recomposition
    LazyColumn { items(sorted) { ... } }
}

// GOOD: Use remember with key
@Composable
fun ItemList(items: List<Item>) {
    val sorted = remember(items) { items.sortedBy { it.name } }
    LazyColumn { items(sorted) { ... } }
}

Missing keys in LazyColumn

// BAD: Index-based identity (causes recomposition on list changes)
LazyColumn {
    items(items) { item -> ItemRow(item) }
}

// GOOD: Stable key-based identity
LazyColumn {
    items(items, key = { it.id }) { item -> ItemRow(item) }
}

Unstable data classes

// BAD: Unstable (contains List, which is not stable)
data class UiState(
    val items: List<Item>,
    val isLoading: Boolean
)

// GOOD: Mark as Immutable if truly immutable
@Immutable
data class UiState(
    val items: ImmutableList<Item>, // kotlinx.collections.immutable
    val isLoading: Boolean
)

Reading state too early

// BAD: State read during composition (recomposes whole tree)
@Composable
fun AnimatedBox(scrollState: ScrollState) {
    val offset = scrollState.value // Recomposes on every scroll
    Box(modifier = Modifier.offset(y = offset.dp)) { ... }
}

// GOOD: Defer state read to layout/draw phase
@Composable
fun AnimatedBox(scrollState: ScrollState) {
    Box(modifier = Modifier.offset {
        IntOffset(0, scrollState.value) // Read in layout phase
    }) { ... }
}

Object allocation in composition

// BAD: Creates new Modifier chain every recomposition
Box(modifier = Modifier.padding(16.dp).background(Color.Red))

// GOOD for dynamic modifiers: Remember the modifier
val modifier = remember { Modifier.padding(16.dp).background(Color.Red) }
Box(modifier = modifier)

Stability Checklist

TypeStable by Default?Fix
Primitives (Int, String, Boolean)YesN/A
data class with stable fieldsYes*Ensure all fields are stable
List, Map, SetNoUse ImmutableList from kotlinx
Classes with var propertiesNoUse @Stable if externally stable
LambdasNoUse remember { }

5. Verify

Ask the user to:

  • Re-run Layout Inspector and compare recomposition counts.
  • Run Macrobenchmark and compare frame timing.
  • Test on a real device with release build.

Summarize the delta (recomposition count, frame drops, jank) if provided.

Outputs

Provide:

  • A short metrics table (before/after if available).
  • Top issues (ordered by impact).
  • Proposed fixes with estimated effort.

References

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Expert checklist and prompts for auditing and fixing Android accessibility issues, especially in Jetpack Compose.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

Expert guidance on setting up and maintaining a modern Android application architecture using Clean Architecture and Hilt. Use this when asked about project structure, module setup, or dependency injection.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

Authoritative rules and patterns for production-quality Kotlin Coroutines onto Android. Covers structured concurrency, lifecycle integration, and reactive streams.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

Guidance on implementing the Data Layer using Repository pattern, Room (Local), and Retrofit (Remote) with offline-first synchronization.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

Production-ready scripts for Android app testing, building, and automation. Provides semantic UI navigation, build automation, log monitoring, and emulator lifecycle management. Optimized for AI agents with minimal token output.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

Expert guidance on setting up scalable Gradle build logic using Convention Plugins and Version Catalogs.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

new-silvermoon/awesome-android-agent-skills9822026년 7월 28일 업데이트

new-silvermoon의 스킬 모두 보기

이 스킬의 문제 신고