$npx -y skills add skydoves/compose-performance-skills --skill tracing-recompositions-at-runtimeUse this skill to instrument a Jetpack Compose composable with @TraceRecomposition from skydoves/compose-stability-analyzer so per-recomposition diffs (which state or parameter changed, what value transition) print to logcat under the Recomposition tag. Works in release-wit
| 1 | # Tracing Recompositions at Runtime — `@TraceRecomposition`, logcat, and the live heatmap |
| 2 | |
| 3 | Layout Inspector counts recompositions and surfaces Argument Change Reasons, but it works **only in debug**, where Live Literals and the interpreted Compose runtime inflate counts. `@TraceRecomposition` from `skydoves/compose-stability-analyzer` instruments a composable at compile time and emits per-recomposition diffs (which state changed, what value transition) to logcat under the `Recomposition` tag. The instrumentation works in any build the developer enables it for — including release-with-debug-symbols — and feeds the IntelliJ / Android Studio plugin's live recomposition heatmap. |
| 4 | |
| 5 | This skill is the **release-mode complement** to `../../recomposition/debugging-recompositions/SKILL.md`. Layout Inspector is debug-only, fast to set up, and good for the first triage. `@TraceRecomposition` is the ground-truth confirmation: instrument the suspect composable, ship a release+R8 build of the dev APK, run the user journey, and read the per-recomposition log lines. |
| 6 | |
| 7 | ## When to use this skill |
| 8 | |
| 9 | - A composable recomposes more than expected and Layout Inspector counts are inconclusive (the count differs between debug and release, or the suspect is an inline composable not covered by Layout Inspector). |
| 10 | - A stability or strong-skipping fix needs to be confirmed against a release-equivalent build before merging. |
| 11 | - A developer wants per-state-and-per-parameter change diffs printed inline rather than clicking through the Layout Inspector tree. |
| 12 | - A team wants to baseline a composable's recomposition count for an SLO ("PriceTicker recomposes ≤ once per price update; never per parent tick"). |
| 13 | - The user mentions `@TraceRecomposition`, "trace recomposition", "compose-stability-analyzer", "recomposition logcat", "recomposition heatmap", or "release-mode recomposition". |
| 14 | |
| 15 | ## When NOT to use this skill |
| 16 | |
| 17 | - The developer just wants recomposition counts in debug — Layout Inspector is faster to set up. See `../../recomposition/debugging-recompositions/SKILL.md`. |
| 18 | - The build is a **production release** with no diagnosis intent — the instrumentation must be gated off. See the runtime-toggle pattern below. |
| 19 | - The team needs a CI gate that fails on **future** stability regressions — runtime tracing is for diagnosis; gating is `../../stability/enforcing-stability-in-ci/SKILL.md` (`stabilityCheck`). |
| 20 | - The need is per-frame timing or end-to-end user-perceived perf, not recomposition counts — that is `../generating-baseline-profiles/SKILL.md` with `MacrobenchmarkRule` + `FrameTimingMetric`. |
| 21 | |
| 22 | ## Prerequisites |
| 23 | |
| 24 | - The Gradle plugin `com.github.skydoves.compose.stability.analyzer` (latest, v0.7.3+) added to the module that owns the composables to instrument. |
| 25 | - An `Application` subclass declared in the manifest, so `ComposeStabilityAnalyzer.setEnabled(...)` can be called from `onCreate()`. |
| 26 | - Compose Compiler reachable from the same module — `org.jetbrains.kotlin.plugin.compose` applied (Kotlin 2.0+). |
| 27 | - A `BuildConfig` field or feature flag the runtime toggle can read. `BuildConfig.DEBUG` works; a custom `BuildConfig.ENABLE_RECOMPOSITION_TRACE` is preferred for production-style profiling builds. |
| 28 | - For the IntelliJ / Android Studio heatmap: the `compose-stability-analyzer` plugin installed from the JetBrains marketplace (or built locally from the GitHub repo). |
| 29 | - Familiarity with `../../recomposition/debugging-recompositions/SKILL.md` so the developer has already named the suspect composable in debug before reaching for runtime tracing. |
| 30 | |
| 31 | ## Workflow |
| 32 | |
| 33 | ### 1. Apply the Gradle plugin |
| 34 | |
| 35 | In the module's `build.gradle.kts`: |
| 36 | |
| 37 | ```kotlin |
| 38 | plugins { |
| 39 | id("com.android.application") |
| 40 | id("org.jetbrains.kotlin.android") |