Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
new-silvermoon avatar

Compose Performance Audit

  • 458 installs
  • 910 repo stars
  • Updated July 27, 2026
  • new-silvermoon/awesome-android-agent-skills

compose-performance-audit is a Claude Code skill that audits Jetpack Compose UI for recomposition waste, layout thrash, and scroll jank for developers who need smooth rendering on low-end Android devices before release.

About

compose-performance-audit is an Android agent skill from new-silvermoon/awesome-android-agent-skills that walks developers through a five-step Jetpack Compose performance workflow: code-first review, guided profiling, root-cause analysis, remediation, and verification. The skill starts by scanning composables for unstable parameters, missing LazyColumn keys, heavy work in composition blocks, and broad state reads that trigger recomposition storms. When code review is inconclusive, it directs developers to Android Studio Layout Inspector recomposition counts, Perfetto or System Trace frame timing, Recomposition Highlights, and Macrobenchmark scroll metrics on release builds with R8 enabled. Remediation guidance covers @Stable and @Immutable data classes, derivedStateOf, remember blocks, stable LazyList keys, and flattening layout hierarchies. Developers reach for compose-performance-audit when scrolling feels janky, recompositions spike, or Compose screens lag on low-end devices but the root cause is unclear between state, layout, or image loading.

  • Recomposition hotspot detection
  • Lazy list optimization
  • Profiler-driven fixes
  • Memory and jank checks
  • Pre-release Compose tuning

Compose Performance Audit by the numbers

  • 458 all-time installs (skills.sh)
  • +14 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #314 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/new-silvermoon/awesome-android-agent-skills --skill compose-performance-audit

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs458
repo stars910
Last updatedJuly 27, 2026
Repositorynew-silvermoon/awesome-android-agent-skills

How do you fix janky Jetpack Compose scrolling and recompositions?

Audit Jetpack Compose UI for recomposition waste, layout thrash, and memory issues before release to keep scrolling smooth on low-end devices.

Who is it for?

Android developers shipping Jetpack Compose apps who see janky scrolling, recomposition storms, or slow rendering on low-end devices.

Skip if: Teams working in XML Views, Flutter, or React Native rather than Jetpack Compose, or projects without Android Studio profiling access.

When should I use this skill?

User reports slow Compose rendering, janky scrolling, excessive recompositions, or asks for a Compose performance audit before release.

What you get

Performance audit findings, recomposition root-cause analysis, remediation checklist, and verified Compose stability fixes for LazyColumn and state reads.

  • performance audit report
  • remediation checklist
  • stability fixes

By the numbers

  • Follows a five-step audit workflow from code review through verification
  • Recommends four profiling tools: Layout Inspector, Perfetto, Recomposition Highlights, Macrobenchmark

Files

SKILL.mdMarkdownGitHub ↗

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

Related skills

How it compares

Pick compose-performance-audit over generic Android lint skills when symptoms are Compose-specific recomposition or scroll jank rather than general APK size or network issues.

FAQ

What profiling tools does compose-performance-audit recommend?

compose-performance-audit recommends Android Studio Layout Inspector for recomposition counts, Recomposition Highlights, Perfetto or System Trace for frame timing, and Macrobenchmark for startup and scroll metrics on release builds with R8 enabled.

When should I start with code review versus profiling?

compose-performance-audit starts with code-first review when Compose source is available. If review is inconclusive, the skill guides profiling with Layout Inspector or Perfetto traces before mapping findings to remediation steps.

What Compose anti-patterns does compose-performance-audit fix?

compose-performance-audit targets unstable parameters, missing LazyColumn keys, heavy work in composition, broad state reads, and layout nesting. Fixes include @Stable annotations, derivedStateOf, remember blocks, and stable list item IDs.

Mobile Developmentfrontendtesting

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.