MWMichael WinklerBlogbymw.de ↗
App & Web-Entwicklung

Ein Zeilen-Update im Build-Skript, und Coroutines starten doppelt so schnell

Google hat vergangene Woche erklärt, wie der Optimierer R8 das Starten und Abbrechen von Kotlin-Coroutines um bis zu das Doppelte beschleunigt – ohne eine einzige Zeile App-Code. Ich erkläre dir, was da passiert, wie du es bekommst und warum du es im Debug-Build niemals messen wirst.

Es gibt zwei Sorten Performance-Gewinn. Die eine kostet dich zwei Wochen Umbau, ein halbes Dutzend neuer Fehler und am Ende sagt der Benchmark „acht Prozent". Die andere bekommst du geschenkt, weil jemand anderes eine Ebene tiefer aufgeräumt hat.

Google hat am 27. Juli 2026 im Android-Entwicklerblog beschrieben, wie eine solche Aufräumaktion aussieht: Der Optimierer R8 macht das Starten und Abbrechen von Kotlin-Coroutines bis zu doppelt so schnell. Dein App-Code bleibt dabei unangetastet. Und weil seit dem 30. Juli das Android Gradle Plugin 9.3.0 zusammen mit Android Studio Quail 3 im stabilen Kanal steht, hat den Gewinn bereits jeder eingesammelt, der sein Projekt in den letzten Tagen aktualisiert hat – vermutlich ohne es zu merken.

Was R8 überhaupt ist

Kurz für alle, die eher von der Website-Seite kommen: R8 ist der Schritt, der beim Bauen einer Android-App den Bytecode zusammenschrumpft. Er wirft ungenutzten Code raus, kürzt Namen ein und – der interessante Teil – schreibt Code um, wenn er beweisen kann, dass die schnellere Fassung dasselbe tut.

Genau da setzt die Neuerung an.

Der eigentliche Trick

Coroutines verwalten intern sehr viel Zustand, der zwischen mehreren Threads sauber bleiben muss. Dafür benutzt die Bibliothek kotlinx.atomicfu sogenannte Field Updater – kleine Helfer, die ein einzelnes Feld eines Objekts atomar setzen. Der Haken: Diese Helfer arbeiten über Reflection. Bei jedem Zugriff prüft die Laufzeitumgebung erneut, ob der Aufrufer das Feld überhaupt anfassen darf. Sicher, aber teuer.

R8 erkennt jetzt die typischen Muster, in denen so ein Field Updater angelegt und benutzt wird, und ersetzt die Aufrufe durch direkte Unsafe-Varianten. Die Sicherheitsprüfung fällt weg, weil der Compiler sie schon beim Bauen erledigt hat. Googles Formulierung dazu:

R8 optimizes most Atomic*FieldUpdater calls into Unsafe variants that perform 2x to 4x better on common operations.

In Zahlen: Eine Operation in kotlinx.atomicfu lag bei 135 Nanosekunden und liegt danach bei rund 50,7 Nanosekunden – also gleichauf mit einem einfachen AtomicReference. Der Umweg über Reflection war praktisch der gesamte Unterschied.

Weil kotlinx.coroutines genau diese Bausteine benutzt, schlägt das direkt durch: Das Starten und Abbrechen einer Coroutine wird bis zu doppelt so schnell. Google nennt als Beispiel LaunchedEffect aus Jetpack Compose – jenen Baustein, mit dem man in einer Compose-Oberfläche einen Effekt an einen Zustand knüpft.

Was du dafür tun musst

Fast nichts. Die Optimierung steckt ab AGP 9.2.0 drin (oder ab R8 9.2.0, wenn du den direkt einbindest) und ist standardmäßig aktiv. In deiner gradle/libs.versions.toml beziehungsweise im Build-Skript reicht die Versionsnummer:

[versions]
agp = "9.3.0"

Danach einmal synchronisieren, fertig. Kein neues Gradle-Flag, keine ProGuard-Regel, keine Änderung an deinem Code.

Und jetzt der Teil, den du wissen musst, bevor du misst

Hier bin ich schon selbst in die Falle getappt, deshalb sage ich es deutlich: R8 läuft nur im Release-Build. In einem Debug-Build ist die Codeverkleinerung standardmäßig aus – es gibt also keinen Optimierer, der irgendetwas umschreibt. Wer den Effekt im Debug-Build sucht, findet ihn nie und hält die Meldung für Marketing.

Prüf deshalb, dass in deinem Release-Block wirklich steht:

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

Ohne isMinifyEnabled = true läuft R8 gar nicht – und dann bringt dir auch die schönste Optimierung im Compiler nichts.

Was das realistisch bringt

Ich mag es nicht, wenn aus „doppelt so schnell" eine Schlagzeile wird, die etwas anderes verspricht als die Messung hergibt. Also ehrlich: Deine App wird nicht doppelt so schnell. Halbiert wird die Zeit, die das Starten und Abbrechen einer Coroutine kostet – ein Vorgang im Bereich von Nanosekunden.

Spürbar wird das dort, wo sehr viele davon stattfinden: in langen, scrollenden Listen, in denen jedes Element seinen eigenen LaunchedEffect startet und beim Wegscrollen wieder abbricht. In Animationen. In Oberflächen, die auf jede Eingabe reagieren. Also genau an den Stellen, an denen eine App sich „billig" anfühlt, ohne dass man den Finger draufhalten kann.

Bei einer App mit drei Bildschirmen und einem Netzwerkaufruf wirst du gar nichts merken. Das ist völlig in Ordnung – es hat dich ja auch nichts gekostet außer einer geänderten Versionsnummer.

Mein Fazit

Wenn du eine Android-App betreust, ist das ein Fünf-Minuten-Handgriff mit garantiert positivem Vorzeichen: AGP aktualisieren, Release-Build prüfen, einmal auf einem echten Gerät durchklicken. Nimm den Anlass gleich mit, um zu schauen, ob dein Release-Build überhaupt minifiziert ist – erfahrungsgemäß ist das häufiger nicht der Fall, als man denkt, und dann liegt dort deutlich mehr Geschwindigkeit brach als in dieser einen Optimierung.

Ich baue Android-Apps in Kotlin mit Jetpack Compose und halte sie danach auch auf Stand – Fristen, Updates, Build-Ketten inklusive. Wenn du gerade eine App hast, die seit zwei Jahren niemand mehr angefasst hat, schau auf bymw.de vorbei. Und wenn du erst mal selbst weiterbasteln willst: Kurze, praktische Code-Beispiele aus Kotlin, Compose und Co. sammle ich auf code.bymw.de.

Quellen

Hat dir der Artikel gefallen?
#Android#Kotlin#Performance#Coroutines

Du hast ein Projekt im Kopf?

Ich entwickle Android-Apps und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →