DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Compose Performance Profiling Guide - Layout Inspector and CPU Profiler

Compose Performance Profiling Guide - Layout Inspector and CPU Profiler

Compose performance optimization starts with measurement. Learn how to profile recompositions, identify bottlenecks, and optimize your UI rendering performance.

Layout Inspector - Recomposition Analysis

Android Studio's Layout Inspector shows recomposition counts and helps identify unnecessary recomposes:

// BAD: Causes excessive recomposition
@Composable
fun BadList(items: List<Item>) {
    LazyColumn {
        items(items) { item ->
            // BAD: Entire lambda captures parent state
            Text("Item: ${item.name}")
            Text("Count: ${calculateCount(item)}")  // Recalculates every time
        }
    }
}

// GOOD: Optimize with keys and stable parameters
@Composable
fun GoodList(items: List<Item>) {
    LazyColumn {
        items(items, key = { it.id }) { item ->
            // GOOD: Stable parameters reduce recomposition
            StableItemRow(item)
        }
    }
}

@Composable
fun StableItemRow(item: Item) {
    Text("Item: ${item.name}")
    Text("Count: ${rememberUpdatedState(calculateCount(item)).value}")
}
Enter fullscreen mode Exit fullscreen mode

Steps to use Layout Inspector:

  1. Run app in Android Studio with debuggable build
  2. Tools → Layout Inspector
  3. Select your app process
  4. Inspect composables and check recomposition counts

@Immutable and @stable Annotations

Mark data classes and state holders to help the Compose compiler optimize:

// Mark immutable data classes
@Immutable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Mark stable custom objects
@Stable
class UserState(
    private val _user: MutableState<User> = mutableStateOf(User(0, "", ""))
) {
    val user: User
        get() = _user.value

    fun updateUser(user: User) {
        _user.value = user
    }
}

@Composable
fun UserCard(user: User) {  // User is immutable, compiler can optimize
    Text(user.name)
    Text(user.email)
}
Enter fullscreen mode Exit fullscreen mode

Compose Compiler Metrics

Enable compiler metrics to see what Compose is doing:

// build.gradle.kts
android {
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.x"
    }
}

// Run with metrics
// ./gradlew assembleDebug -Pandroid.enableComposeCompilerMetrics=true

// Analyze output in build/compose_metrics/
Enter fullscreen mode Exit fullscreen mode

Metrics files show:

  • composables_metrics.txt: Recomposition groups and stability info
  • classes_metrics.txt: Compiled composable classes
  • module-classes_metrics.txt: Module-level analysis

CPU Profiler with Trace API

Use Trace API for granular performance analysis:

import androidx.tracing.trace

@Composable
fun PerformanceCriticalScreen() {
    trace("ScreenComposition") {
        val data = rememberCoroutineScope().launch {
            trace("DataLoading") {
                loadData()
            }
        }

        LazyColumn {
            items(data) { item ->
                trace("ItemRow-${item.id}") {
                    ItemRow(item)
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Key Performance Optimization Patterns

Optimization Technique Impact
Reduce recompose remember, key {} High
Stable parameters @Immutable, @Stable High
Lazy layouts LazyColumn, LazyRow High
State holders rememberXxxState() Medium
Compiler hints Type annotations Medium
Memoization derivedStateOf {} Medium

remember vs derivedStateOf

@Composable
fun OptimizedScreen(input: String) {
    // Bad: Recalculates on every recomposition
    val result = expensiveCalculation(input)

    // Good: Only recalculates if input changes
    val result = remember(input) {
        expensiveCalculation(input)
    }

    // Best: For derived state, updates only when result changes
    val memoizedResult = remember(input) {
        expensiveCalculation(input)
    }
    val derived = derivedStateOf { memoizedResult.uppercase() }
}
Enter fullscreen mode Exit fullscreen mode

8 Android app templates available on Gumroad

Top comments (0)