Fallstudien

Grab reduziert ANR-Fehler um 32% und verbessert die Startzeit um 35% mit R8 und profilgesteuerter Optimierung

Lesezeit: 5 Minuten

Grab ist die führende Super-App in Südostasien und bietet Millionen von Nutzern in acht Ländern Liefer-, Mobilitäts- und Finanzdienstleistungen über eine einzige App. Mit einer zehn Jahre alten Codebasis, die mehr als zehn Millionen Codezeilen und Hunderte von Drittanbieterbibliotheken enthält, die mit einer hybriden Bazel- und Gradle-Konfiguration erstellt wurden, stand das Grab-Team vor drei wachsenden Herausforderungen: hohe ANR-Raten (App antwortet nicht), eine App-Größe, die mit dem Hinzufügen neuer Dienste zur Super-App immer weiter zunahm, und eine Startzeit, die sich im Jahresvergleich langsam erhöhte. Durch die Aktivierung der R8-Optimierung, die Verfeinerung von Beibehaltungsregeln und die Implementierung von Baseline- und Startprofilen konnte Grab die Rate der vom Nutzer wahrgenommenen ANR-Fehler um 32 % senken, die Downloadgröße der App um etwa 30 % reduzieren und die Startzeit um 35 % verbessern.

Eliminating Post-Release ANR Spikes for a Smoother User Experience

Vor der Optimierung des Build-Prozesses kam es bei Grab unmittelbar nach neuen Updates zu Verzögerungen beim Kaltstart und zu Spitzen bei ANR-Fehlern (App reagiert nicht). Dies lag hauptsächlich am Aufwand, der durch das Lesen vieler DEX-Dateien während der App-Initialisierung entstand. 

Die Cloud-Profile von Google Play optimieren zwar Standardabläufe für die gesamte Nutzerbasis, aber nicht alle Initialisierungspfade, die für die Critical User Journeys von Grab erforderlich sind, wie die Initialisierung von Dagger-Abhängigkeitsdiagrammen beim App-Start. Für Codepfade, die nicht in der ursprünglichen Verteilung enthalten waren, wurden auf den Geräten in den folgenden Tagen die Just-in-time-Kompilierung und die lokale Hintergrundoptimierung verwendet. Durch die Implementierung eines benutzerdefinierten Baseline-Profils wurde dieses Problem behoben, da diese kritischen User Journeys direkt in die Cloud-Profile von Google Play aufgenommen wurden. Dadurch wurde die Optimierungsabdeckung erweitert, sodass diese wichtigen Pfade sofort bei der Installation in Maschinencode kompiliert wurden. 

ANDDM_Grab_Inline_Quote_ALT.png

„Wir hatten bei jedem wöchentlichen App-Release immer wieder Spitzen bei der ANR-Rate“, erklärt Nguyen Van Minh, Lead Software Engineer im Passenger App Core-Team von Grab. 

Um ANR-Fehler zu vermeiden und die Startzeiten zu verbessern, hat Grab R8-Optimierungen, Baseline-Profile und Startprofile implementiert. Die profilgesteuerte Optimierung in Kombination mit dem R8-Optimierer führte zu einer sofortigen Verbesserung des Kaltstarts um 12% durch R8 und um weitere 15% durch Baseline-Profile. Dadurch wurde die Startzeit um 27% verkürzt und die ANR-Spitzen nach dem Release wurden effektiv beseitigt.

Grab hat diese App-Optimierung in drei strategischen Phasen durchgeführt: Aktivierung der R8-Optimierung im Kompatibilitätsmodus, Umstellung auf den R8-Vollmodus und anschließende Verfeinerung der Keep-Regeln mit dem Configuration Analyzer sowie Hinzufügen von CI/CD-Governance.

Phase 1: R8-Optimierung aktivieren  (2025 eingeführt)

In dieser ersten Phase hat Grab die standardmäßige Proguard-Datei durch proguard-android-optimize.txt ersetzt, wodurch R8-Optimierungen ermöglicht werden.  Da die Codebasis über ein Jahrzehnt alt war und mehr als 10 Millionen Codezeilen enthielt, mussten für die Aktivierung des Optimierers Legacy-Konfigurationen und die Verwendung von Reflexionen berücksichtigt werden.

Um die Wirkung dieser Phase zu maximieren, hat Grab das App-Update mit aktiviertem R8-Kompatibilitätsmodus mit Baseline- und Startprofilen veröffentlicht. Diese kombinierten Maßnahmen führten zu einer sofortigen Reduzierung der Rate der vom Nutzer wahrgenommenen ANR-Fehler um 25 %, einer Reduzierung der Downloadgröße der App um 16% und einer allgemeinen Verbesserung der Kaltstartzeiten um 27 %.

Phase 2: R8-Vollmodus und Migration (veröffentlicht 2026)

In dieser Phase, die neun Monate nach dem ersten Roll-out begann, wurde die App in den vollständigen R8-Modus versetzt, was weitere Optimierungen ermöglichte. Standardbibliotheken wie Retrofit, Firebase und Jetpack Compose funktionierten dank ihrer integrierten Regeln nahtlos mit R8. Die Migration des restlichen umfangreichen Codebestands wurde durch die Behebung bestimmter reflexionsintensiver Codepfade erreicht:

Für die Migration zum R8-Vollmodus hat das Team die Consumer-Keep-Regeln aus der neuesten Gson-Version übernommen, um ein nahtloses JSON-Parsing zu ermöglichen. Außerdem wurden Optimierungsprobleme mit dynamischen Java-Proxys behoben, die Reflexion verwenden, um Schnittstellenimplementierungen zur Laufzeit zu generieren. Da R8 diese Laufzeitnutzung während der Kompilierung nicht erkennen kann, werden die erforderlichen Klassen entfernt oder umbenannt, was zum Absturz der Anwendung führt. Anstatt allgemeine Ausnahmen anzuwenden, die die App-Größe erhöhen würden, isolierte das Team die spezifischen Klassen, die auf Reflexion basieren, und implementierte gezielte Beibehaltungsregeln. So wurden sowohl die App-Stabilität als auch die Optimierungseffizienz gewahrt.

Letztendlich lieferte der R8-Vollmodus massive, sich gegenseitig verstärkende Verbesserungen, darunter eine zusätzliche Reduzierung der Downloadgröße der App um 14 %, eine weitere Verbesserung der Startzeit um 10% und eine weitere Verringerung der von Nutzern wahrgenommenen ANR-Fehler um 10 %. Nach der Migration zum R8-Vollmodus erreichte die Codebasis von Grab diese R8-Optimierungsfaktoren. 

  • Optimierungsfaktor: 72%
  • Wert für die Entfernung von Ressourcen: 73%
  • Verschleierungswert: 79,6%

Diese Werte gaben Feedback zur R8-Konfiguration und zur Notwendigkeit, die Keep-Regeln zu verfeinern, um die R8-Optimierung zu maximieren. 

Phase 3: Optimierung der Aufbewahrungsregeln 

In der letzten Phase der Optimierung konzentriert sich Grab auf die langfristige Verbesserung der Codebasis, die kontinuierliche Leistungsüberwachung und die strikte Governance der Kompilierung. Um die Regelhygiene systematisch zu messen und Konfigurationsregressionen über laufende Releasezyklen hinweg zu verhindern, integriert das Team den R8 Configuration Analyzer in seinen Bewertungsworkflow. Dieses Tool bietet einen tiefen Einblick, wie effektiv die Keep-Regeln von Grab es R8 ermöglichen, die Anwendung zu optimieren, zu verkleinern und zu verschleiern.

Durch die Nutzung des R8-Vollmodus und das systematische Entfernen veralteter Keep-Regeln erzielt Grab erhebliche Verbesserungen in allen drei vom Analyzer bewerteten Kerndimensionen:

  • Optimierungsfaktor: steigt von 72% auf 78,2%
  • Wert für die Entfernung von Ressourcen: steigt von 73% auf 79,1%
  • Verschleierungswert: steigt von 79,6% auf 81,7%

Neben der Verbesserung dieser Diagnosewerte führt diese Phase der Verfeinerung der Keep-Regeln zu einer zusätzlichen Reduzierung der Downloadgröße der App um etwa 3, 6 %. Noch wichtiger ist, dass das Engineering-Team durch das Erfassen dieser Messwerte die objektiven Daten erhält, die es benötigt, um automatisierte CI-Schutzmaßnahmen vor dem Zusammenführen zu implementieren. So wird sichergestellt, dass neu eingeführter Code den strengen Keep-Rule-Standards entspricht und dass die mühsam erzielten Leistungssteigerungen im Laufe der Zeit erhalten bleiben.

Ergebnisse

Wichtige Leistungsverbesserungen nach der Einführung des R8-Optimierers:

OptimierungsphaseANRsGrößeKaltstart
Phase 1: R8-Optimierungstool (veröffentlicht 2025)~25% Reduzierung16% weniger~27% Verbesserung
Phase 2: R8-Vollmodus (veröffentlicht 2026)10% Reduzierung14% weniger10% Verbesserung
Optimierung von Aufbewahrungsregeln-3,6% weniger-
Gesamt (kumulativ)~32,5% Reduzierung~30,4% Reduzierung~35% Verbesserung

Technische Herausforderungen 

Die Aktivierung des R8-Optimierers in der zehn Jahre alten Codebasis von Grab brachte erhebliche technische Hürden mit sich:

  • Tests: Ein Jahrzehnt angesammelter Reflexionen führte bei vollständiger Optimierung zu Grenzfällen. Da umfassende Tests für Millionen von Codezeilen unmöglich waren, ging das Team schrittweise vor und konzentrierte sich auf die wichtigsten Bereiche. Die Tests wurden speziell auf den Code ausgerichtet, der von den eingeschränkten Keep-Regeln abgedeckt wurde. Diese Regeln wurden iterativ verfeinert, um nur die spezifischen Klassen, Methoden oder Felder zu berücksichtigen, die für die Reflexion erforderlich waren, um die R8-Optimierung zu maximieren.
  • Build-Latenz und Hybridarchitektur:Aufgrund des hybriden Build-Systems von Grab (Bazel für Debugging, Gradle für R8-Release-Builds) dauerten experimentelle R8-Änderungen in der Remote-CI bis zu 2 Stunden. Um die Feedbacklücke zu schließen, hat Grab seine täglichen QA-Builds an das Verhalten von R8 in der Produktion angepasst und die Erfassung wichtiger CI-Build-Artefakte wie mapping.txt und configuration.txt automatisiert, um die Untersuchung zu optimieren.
  • Langsame Debugging-Zyklen: Die Ursachenforschung in Hunderten von optimierten Klassen war für ein kleines Team eine große Belastung. Grab hat dieses Problem gelöst, indem das Unternehmen das Hochladen von Zuordnungsdateien in Firebase Crashlytics über Gradle automatisiert und Deobfuskationszuordnungen für die Play Console gebündelt hat. So können Laufzeitprobleme sofort und genau aufgelöst werden.

Langfristige Auswirkungen von R8 auf den Code

Neben den unmittelbaren Leistungssteigerungen brachte die Aktivierung des R8-Optimierers einen dauerhaften strukturellen Vorteil für die riesige Codebasis von Grab. Das Team von Grab hat das Open-Source-Tool app-sizer verwendet, um die Auswirkungen von R8 zu messen. Dabei wurde festgestellt, dass R8 die Downloadgröße jeder Codezeile in der App dauerhaft reduziert hat.

ANDDM_Grab_Inline_Metric.png

Im Zeitalter der KI-gestützten Entwicklung, in dem das Codevolumen rasant zunimmt, ist diese Optimierung noch wichtiger. Ohne R8 erhöht sich die Downloadgröße proportional zur Codeerweiterung. R8 sorgt dafür, dass bei gleicher Codeerweiterungsrate der Speicherbedarf drastisch reduziert wird.

Hinweis: Methodik: Beitrag von Kotlin/Java zur Downloadgröße der App (repräsentatives Gerät) laut app-sizer, geteilt durch die Anzahl der Kotlin-Codezeilen in der Produktion (cloc; nur Haupt-Source-Sets; Test-, Mock- und Beispielmodule ausgeschlossen).

Regelverwaltung und Schutzmaßnahmen für Google Notizen

Um eine Verschlechterung der Regeln zu verhindern und die R8-Optimierungen langfristig beizubehalten, plant Grab, automatisierte Pre-Merge-Guardrails direkt in die CI-Pipeline zu integrieren. Gemäß dieser Richtlinie sind neue Aufbewahrungsregeln streng eingeschränkt. Für alle zusätzlichen Regeln ist eine ausdrückliche Begründung und Überprüfung erforderlich. Das Team von Grab verfolgt die R8-Optimierungsfaktoren in der CI. Darauf aufbauend plant das Team, diese Messwerte als kontinuierliche Feedback-Schleife zu nutzen, damit Regressionen vor dem Zusammenführen erkannt werden und Optimierungsgewinne über jeden Releasezyklus hinweg erhalten bleiben. 

R8-rules-score (1).png

Abbildung 1: CI-Dashboard, das die R8-Werte für Verkleinerung, Optimierung und Verschleierung im Zeitverlauf in Grab-Builds erfasst, um Regressionen in verschiedenen Releases proaktiv zu erkennen und zu verhindern.

Fazit 

Angesichts der Herausforderungen einer riesigen, immer komplexer werdenden Codebasis hat das Pax App Core-Team von Grab proaktiv die zunehmenden Startzeiten und Leistungsspitzen nach dem Release in Angriff genommen. Dazu wurden Baseline-Profile implementiert und die R8-Konfiguration kontinuierlich verbessert. Das Team konnte die von Nutzern wahrgenommenen ANR-Fehler um ca. 32,5 % reduzieren, die Downloadgröße der App um ca. 30,3 % verringern und die Kaltstartzeit um ca. 35 % verbessern. Gleichzeitig wurde die Effizienz der Skalierung der Codebasis grundlegend verbessert.

Diese Optimierungen sorgten für eine schnellere und stabilere Super-App für Millionen von Nutzern in Südostasien. Gleichzeitig erhielten die Entwickler von Grab die Tools, um Funktionen schneller zu entwickeln, ohne dass die Downloadgröße rasant anstieg.

Weitere Informationen zu R8 finden Sie unter - d.android.com/r8.

Verfasst von:
Weiterlesen