AUGUST 5, 2026
R8 Made Kotlin Coroutines 2x Faster on Android
R8 made Kotlin coroutines 2x faster on Android by replacing Atomic*FieldUpdater calls with Unsafe variants in AGP 9.2.0.
By Entalogics Team · Programming


R8’s coroutine speedup in Android apps
R8 changed the performance profile of Kotlin coroutines on Android. Starting with AGP 9.2.0, it optimizes most Atomic*FieldUpdater calls into Unsafe variants that perform 2x to 4x better on common operations. In practice, that shows up where many Android teams care most: coroutine launch, cancellation, and UI-adjacent work that happens outside composition.
The Android team says the impact is especially large for kotlinx.atomicfu, the library that underpins atomics in kotlinx.coroutines. After the optimization, launching and cancelling coroutines became up to 2x faster. For teams chasing frame-time wins, that is a meaningful shift. For teams shipping coroutine-heavy UI, it is the kind of backend compiler change that can move user-facing benchmarks without touching application code.
Starting from AGP 9.2.0, R8 optimizes most Atomic*FieldUpdater calls into Unsafe variants that perform 2x to 4x better on common operations.
Why Kotlin coroutines slowed down before R8
The performance problem was not coroutines in the abstract. It was the work around them. Compose’s team found that coroutines were a bottleneck for many operations outside of composition, and one example showed how much that matters in real code. In the Modifier.clickable path, 80% of the time spent on creating and updating Modifier.clickable went into launching and cancelling internal coroutines that handled InteractionSource updates.
That kind of profile is easy to miss if you only look at application logic. The hot path is not always the obvious one. A tiny internal coroutine can dominate a UI action if it runs often enough.
A second clue came from the way an empty LaunchedEffect breaks down. The Android post describes 3 parts: initializing a new coroutine, starting it, and completing it immediately. Cancelling LaunchedEffect follows the same pattern, but adds a CancellationException.
That matters because every one of those steps is overhead. When the work being wrapped is small, the setup cost can outweigh the useful work. R8’s change targets exactly that overhead.
How R8 optimizes Atomic*FieldUpdater calls
The optimization is straightforward in concept. R8 can replace the updater field with an offset field and replace updater calls with Unsafe calls. In the Android blog’s example, the new call site uses compareAndSwapObject on SyntheticUnsafe.UNSAFE.
The implementation itself is split into 3 parts: Instrumentation, Replacement, and Clean-up. First, R8 instruments the code so it can identify the relevant updater pattern. Then it rewrites the call path. Finally, it removes the pieces that are no longer needed after the replacement.
That approach is important because the optimization is not a source-level trick. It happens during the build. Teams do not need to rewrite coroutine code to get the benefit. They need the right toolchain version.
The Android team also notes that the ART team is implementing similar optimizations at the VM level. That gives a hint about where this kind of performance work is headed: less framework overhead, more runtime help, and fewer Java-level indirections in the middle.
Ship faster with senior engineers
Direct collaboration, AI-augmented delivery, and no agency markup.
Get in touchBenchmark results on Pixel 5
The Android post includes a concrete benchmark on a Pixel 5 running API 33. In that test, AtomicReference.compareAndSet took 50.7 ns, while the kotlinx.atomicfu version took 135 ns. The kotlinx.atomicfu path was approximately 2.7x slower in that benchmark.
On a Pixel 5 running API 33, AtomicReference.compareAndSet took 50.7 ns while the kotlinx.atomicfu version took 135 ns.
That gap is why the optimization matters. The Android team says that after these optimizations, kotlinx.atomicfu and most explicit AtomicInt/Long/ReferenceFieldUpdater uses now match AtomicReference performance with R8 applied. In some benchmarks, they are even faster than AtomicReference because kotlinx.atomicfu can inline atomic instances into fields and reduce allocations.
This is the kind of result that can change a team’s tuning priorities. If a benchmark is dominated by atomics, the compiler can now do some of the work that once sat on your profile flame graph.
What changed for Compose benchmarks
The Compose team saw the effect when benchmark results were updated to a new version of R8. They noticed a 2x improvement when launching and cancelling coroutines in LaunchedEffect. The blog says the graph change corresponds to an R8 update.
That is a useful reminder for Android teams: build tooling can be a runtime performance feature. A codebase can stay the same while the app gets materially faster because the compiler sees a better lowering opportunity.
For Compose-heavy apps, the lesson is simple. If your UI work includes lots of small coroutine operations, you should measure again after adopting the newer toolchain. A speedup in coroutine setup and teardown can ripple into event handling, interaction feedback, and any code that relies on short-lived concurrent work.
If you want to see how this kind of performance problem shows up in broader mobile systems, read our mobile app performance optimization guide. It covers how to spot bottlenecks that are hidden behind framework code.
What Android teams should do now
The optimization is available by default with AGP 9.2.0 or R8 9.2.0 directly. That is the first step: upgrade the toolchain. If your app uses kotlinx.coroutines, kotlinx.atomicfu, or custom atomic field updaters, confirm that the optimized path is present in your build output.
Then benchmark the spots that matter. Look at coroutine launch and cancellation in UI interactions, especially where work happens outside composition. The Compose example is a good warning sign, not an edge case. If 80% of the time is being spent on coroutine setup and teardown in one interaction path, that is a candidate for measurement and refactoring.
If you publish Android libraries, this change also matters for your consumers. Tooling gains can affect downstream apps in ways that source code reviews will not catch. That is one reason teams doing platform work often ask for independent review of build and runtime assumptions. If that is your situation, the AI Code Security Audit is not just about AI-generated code; it is also a good fit when you need a hard look at the parts of the build pipeline that shape production behavior.
The practical takeaway is clear: upgrade to AGP 9.2.0, rerun your coroutine benchmarks, and inspect the hot paths where atomics and cancellation dominate. If your app is still paying the old cost, R8 can now remove a lot of it for you.