<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5" -->

---
title: How R8 made Kotlin Coroutines on Android 2x faster
description: Starting with AGP 9.2.0, R8 now optimizes most `Atomic*FieldUpdater` calls into direct `Unsafe` variants, eliminating costly reflective safety checks at...
canonical: https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: How R8 made Kotlin Coroutines on Android 2x faster | daily.dev
og:description: Starting with AGP 9.2.0, R8 now optimizes most `Atomic*FieldUpdater` calls into direct `Unsafe` variants, eliminating costly reflective safety checks at...
og:url: https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5
og:image: https://api.daily.dev/og/posts/baiNtFVs5.png
og:image:alt: How R8 made Kotlin Coroutines on Android 2x faster
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How R8 made Kotlin Coroutines on Android 2x faster

**[Android Developers Blog](https://daily.dev/sources/androiddev)** · 9 min read · 6 upvotes · 0 comments

## Summary

Starting with AGP 9.2.0, R8 now optimizes most `Atomic*FieldUpdater` calls into direct `Unsafe` variants, eliminating costly reflective safety checks at runtime. This change delivers a 2x–4x speedup on common atomic operations and has a major impact on `kotlinx.atomicfu`, the library underpinning `kotlinx.coroutines`. As a result, launching and cancelling coroutines in Android apps — including Jetpack Compose's `LaunchedEffect` — is up to 2x faster. The post explains the root cause (ART does not JIT-optimize `AtomicReferenceFieldUpdater` the way the JVM does), walks through benchmarks confirming the overhead, and details how R8 performs the optimization in three phases: instrumentation (adding an offset field), replacement (rewriting call sites to use `Unsafe` directly), and clean-up (removing dead updater fields and initializers). Apps targeting API 36 may also benefit from similar optimizations being added natively to ART's JIT. Upgrading to AGP 9.2.0 is all that's needed to get the improvement.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://android-developers.googleblog.com/2026/07/how-r8-made-kotlin-coroutines-2x-faster.html>

## Questions this post answers

### How do I get the R8 coroutine performance improvement in my Android app?

Upgrade Android Gradle Plugin (AGP) to version 9.2.0 or above, or use R8 9.2.0 directly. Starting with that version, R8 automatically optimizes most Atomic*FieldUpdater calls into faster Unsafe variants, which can make launching and cancelling coroutines in kotlinx.coroutines up to 2x faster without any code changes.

_daily.dev surfaces build-tooling upgrades like this so app performance work doesn't stall on outdated Android tooling._

### Why is kotlinx.atomicfu slower than java.util.concurrent.atomic.AtomicReference on Android?

Benchmarks on a Pixel 5 (API 33) showed AtomicReferenceFieldUpdater.compareAndSet taking about 135 ns versus 50.7 ns for AtomicReference.compareAndSet, roughly 2.7x slower. The overhead comes from reflective safety checks that AtomicReferenceFieldUpdater must run at runtime to verify field existence and access, checks that Android Runtime (ART) does not eliminate through JIT or AOT compilation.

_benchmarking JVM primitives against Android runtime behavior is easier when relevant deep dives surface automatically on daily.dev._

### How does R8 optimize AtomicReferenceFieldUpdater calls into Unsafe calls?

R8 statically analyzes updater fields created with constant, statically obvious arguments (holder class, field type, field name), then instruments an offset field alongside the original updater, rewrites call sites to use Unsafe.compareAndSwapObject with that offset directly, and cleans up unused fields once all call sites are optimized. This removes the reflective safety checks while preserving null-check semantics where they can't be statically ruled out.

_understanding compiler-level optimizations like this helps developers reason about coroutine performance beyond daily.dev's own reading list._

## Similar posts on daily.dev

- [Android Developers Blog: Use R8 to shrink, optimize, and fast-track your app](https://daily.dev/posts/android-developers-blog-use-r8-to-shrink-optimize-and-fast-track-your-app-phr0xzn6m) · Android Developers Blog · 0 upvotes · 0 comments
- [Enabling R8 optimization at scale with AI-assisted debugging](https://daily.dev/posts/enabling-r8-optimization-at-scale-with-ai-assisted-debugging-kovtjstfc) · Grab Tech Blog · 0 upvotes · 0 comments
- [18% Faster Compiles, 0% Compromises](https://daily.dev/posts/18-faster-compiles-0-compromises-jbenicddz) · Android Developers Blog · 0 upvotes · 0 comments
- [Google Boosts ART Compile Times by 18% Without Compromising Code Quality](https://daily.dev/posts/google-boosts-art-compile-times-by-18-without-compromising-code-quality-yufp5136b) · InfoQ · 0 upvotes · 0 comments

---

Tags: [#android](https://daily.dev/tags/android), [#kotlin](https://daily.dev/tags/kotlin), [#jetpack-compose](https://daily.dev/tags/jetpack-compose)

[View this post on daily.dev](https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"How R8 made Kotlin Coroutines on Android 2x faster","url":"https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5"},"datePublished":"2026-07-27T16:03:44.560Z","dateModified":"2026-09-13T21:06:59.431Z","description":"Starting with AGP 9.2.0, R8 now optimizes most `Atomic*FieldUpdater` calls into direct `Unsafe` variants, eliminating costly reflective safety checks at...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/a86eca152bc17ae2c48ddfacdec2cc82?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/a86eca152bc17ae2c48ddfacdec2cc82?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Android Developers Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Android Developers Blog","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/a3d55bb1d63c48e7bd91b833eb5c2c3c","url":"https://daily.dev/sources/androiddev"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":6},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"android,kotlin,jetpack-compose","timeRequired":"PT9M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Android Developers Blog","item":"https://daily.dev/sources/androiddev"},{"@type":"ListItem","position":3,"name":"How R8 made Kotlin Coroutines on Android 2x faster"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/how-r8-made-kotlin-coroutines-on-android-2x-faster-baintfvs5#faq","mainEntity":[{"@type":"Question","name":"How do I get the R8 coroutine performance improvement in my Android app?","acceptedAnswer":{"@type":"Answer","text":"Upgrade Android Gradle Plugin (AGP) to version 9.2.0 or above, or use R8 9.2.0 directly. Starting with that version, R8 automatically optimizes most Atomic*FieldUpdater calls into faster Unsafe variants, which can make launching and cancelling coroutines in kotlinx.coroutines up to 2x faster without any code changes. daily.dev surfaces build-tooling upgrades like this so app performance work doesn't stall on outdated Android tooling."}},{"@type":"Question","name":"Why is kotlinx.atomicfu slower than java.util.concurrent.atomic.AtomicReference on Android?","acceptedAnswer":{"@type":"Answer","text":"Benchmarks on a Pixel 5 (API 33) showed AtomicReferenceFieldUpdater.compareAndSet taking about 135 ns versus 50.7 ns for AtomicReference.compareAndSet, roughly 2.7x slower. The overhead comes from reflective safety checks that AtomicReferenceFieldUpdater must run at runtime to verify field existence and access, checks that Android Runtime (ART) does not eliminate through JIT or AOT compilation. benchmarking JVM primitives against Android runtime behavior is easier when relevant deep dives surface automatically on daily.dev."}},{"@type":"Question","name":"How does R8 optimize AtomicReferenceFieldUpdater calls into Unsafe calls?","acceptedAnswer":{"@type":"Answer","text":"R8 statically analyzes updater fields created with constant, statically obvious arguments (holder class, field type, field name), then instruments an offset field alongside the original updater, rewrites call sites to use Unsafe.compareAndSwapObject with that offset directly, and cleans up unused fields once all call sites are optimized. This removes the reflective safety checks while preserving null-check semantics where they can't be statically ruled out. understanding compiler-level optimizations like this helps developers reason about coroutine performance beyond daily.dev's own reading list."}}]}
```

