Stop Guessing Your Performance Bottlenecks: Profiling a 3D Compose Showcase on Real Hardware

While engineering a Nike-inspired 3D e-commerce showcase in Jetpack Compose, I ran into a classic UI jank issue on screen transitions. My first theory was Android's predictive back gesture. My second theory was Compose recomposition loops fighting the UI thread. I was wrong on both counts.

What the data actually said

Profiling real frame-timing data on a physical Pixel 8 Pro using Android's frame-stats tooling told a different story:

  • GPU render times were consistently fast — under 3ms. The UI thread was the bottleneck, not the GPU.
  • Android Studio's Layout Inspector was still attached to the running process, actively stealing CPU cycles inside the app's own trace.
  • The real fix was smaller than either theory: adding a stable key() on cross-fading list content, and eliminating a double-computation loop that was running per frame.

The lesson

If you don't profile on real hardware, you aren't optimizing — you're making educated guesses, and educated guesses on Compose specifically tend to point at recomposition or gesture handling first because those are the fashionable suspects. The actual bottleneck is often a tooling artifact or a stale key, and you only find that by measuring instead of theorizing.