·
1 commit
to main
since this release
A controlled Macrobenchmark comparison of five ways to load images in a Jetpack
Compose list, focused on one question: how much does SubcomposeLayout actually
cost, compared to plain Canvas drawing or plain recomposition?
Full write-up, methodology, and results table: docs/benchmark/2026-coil-subcomposition/SUMMARY.md
Strategies compared
AsyncImage(Direct Canvas) — zero subcompositionAsyncImage+ Composable Overlay — Canvas image, Composable error screen only on failureSubcomposeAsyncImage(named slots:loading/success/error)SubcomposeAsyncImage(monolithiccontentlambda, manualwhen(state))rememberAsyncImagePainter+ manualwhen(state)in a plainBox
Setup
- 500 cards, fully local assets, dynamic aspect ratios, deterministic per-item decode
delay and error injection — no network involved anywhere. - Two physical devices: Samsung SM-T595 (Android 10, API 29) and Samsung SM-G9750
(Android 12, API 31). No emulator. CompilationMode.Full(),StartupMode.WARM, release-like build (R8 minified,
non-debuggable, profileable), fixed theme, system animations off, airplane mode on.
Key findings
- The bottleneck depends on the device class, not just the API. On the older
device, theSubcomposeAsyncImagestrategies fall behind on P90/P95. On the
flagship, the ranking flips —rememberAsyncImagePainterbecomes the worst
performer instead, due to a documented API quirk unrelated to subcomposition. - The effect lives in P90/P95, not in P99. The tail (P99) is dominated by a factor
shared by all five strategies; the architectural difference shows up clearly one
step before that. AsyncImage(Direct Canvas) is fastest overall, but has no real error screen.
Among the strategies that do render a proper Composable error UI,AsyncImage+
Composable Overlay is the most consistent choice, at almost no measured cost over
the fastest option.
What's attached to this release
- Aggregated result tables
- The results chart (
frame_duration_by_percentile.png)
Reproducibility
- Code snapshot: this tag
- Kotlin 2.4.20 · Compose BOM 2026.09.00 · Coil 3.6.2 · AGP 9.4.0 · Hilt 2.60.1
- Dataset: 500 items, fixed decode delays and error flags (seeded, not randomized)