Anwendungsleistung messen – Übersicht

In diesem Dokument erfährst du, wie du wichtige Leistungsprobleme deiner App erkennen und beheben kannst.

Wichtige Leistungsprobleme

Es gibt viele Probleme, die zu einer schlechten Leistung einer App führen können, Im Folgenden sind einige häufige Probleme aufgeführt, nach denen Sie in Ihrer App Ausschau halten sollten:

Startlatenz

Die Startverzögerung ist die Zeitspanne zwischen dem Tippen auf das App-Symbol, die Benachrichtigung oder einen anderen Einstiegspunkt und dem Einblenden der Daten des Nutzers auf dem Bildschirm.

Folgende Ziele für Start-ups sollten in Ihren Apps angestrebt werden:

  • Kaltstart in weniger als 500 ms. Ein Kaltstart erfolgt, wenn die gestartete App nicht im Arbeitsspeicher des Systems vorhanden ist. Das ist der Fall, wenn die App zum ersten Mal seit dem Neustart oder seit dem Beenden des App-Prozesses durch den Nutzer oder das System gestartet wird.

    Ein Warmstart findet hingegen statt, wenn die App bereits in im Hintergrund. Ein Kaltstart erfordert die meiste Arbeit im System, muss alles aus dem Speicher geladen und die App initialisiert werden. Versuchen Sie, damit Kaltstarts 500 ms oder weniger dauern.

  • Die P95- und P99-Latenzen liegen sehr nahe an der Medianlatenz. Wenn die App lange am Anfang dauert, ist die User Experience schlecht. Interprocess Communication (IPCs) und unnötige E/A-Vorgänge während kann es beim Start der App zu Sperrkonflikten kommen zu Inkonsistenzen führen.

Ruckeln beim Scrollen

Mit dem Begriff Jank wird der visuelle Schluckauf beschrieben, der auftritt, wenn die nicht in der Lage ist, Frames zu erstellen und rechtzeitig bereitzustellen, Bildschirm mit der gewünschten Frequenz von 60 Hz oder höher. Schwankungen treten am deutlichsten auf, beim Scrollen statt beim animierten Ablauf kommt es zu Problemen. Ruckler treten auf, wenn die Bewegung für einen oder mehrere Frames pausiert, da das Rendern von Inhalten in der App länger dauert als die Dauer eines Frames auf dem System.

Apps müssen auf eine Aktualisierungsrate von 90 Hz ausgerichtet sein. Herkömmliche Renderingraten betragen 60 Hz, Neuere Geräte arbeiten jedoch bei Nutzerinteraktionen im 90-Hz-Modus, wie Scrollen. Einige Geräte unterstützen sogar noch höhere Frequenzen von bis zu 120 Hz.

Um zu sehen, welche Aktualisierungsrate ein Gerät zu einem bestimmten Zeitpunkt verwendet, aktivieren Sie eine mithilfe von Entwickleroptionen > Aktualisierungsrate unter Debugging anzeigen .

Nicht reibungslose Übergänge

Dies wird bei Interaktionen wie dem Wechseln zwischen Tabs oder beim Laden von einer neuen Aktivität. Diese Arten von Übergängen müssen flüssige Animationen sein und dürfen keine Verzögerungen oder visuelles Flimmern enthalten.

Ineffiziente Energienutzung

Durch Arbeit wird der Akku geschont, während unnötige Arbeiten den Akku schonen. Leben.

Die Speicherzuweisung, die durch das Erstellen neuer Objekte im Code verursacht wird, kann zu erheblichen Arbeitslasten im System führen. Das liegt daran, dass nicht nur die Zuweisungen selbst von der Android Runtime (ART) beansprucht werden, sondern auch das spätere Freigeben dieser Objekte (Garbage Collection) Zeit und Aufwand erfordert. Sowohl die Zuweisung als auch die Erfassung sind viel schneller und effizienter. insbesondere für temporäre Objekte. Früher war es Best Practice, sollten möglichst keine Objekte zugewiesen werden. für Ihre App und Architektur am sinnvollsten ist. Bei ART ist es nicht empfehlenswert, bei der Zuweisung zu sparen, wenn dadurch der Code nicht mehr wartbar ist.

Dies ist jedoch mit Aufwand verbunden, denken Sie also daran, wenn Sie viele Objekte in Ihrer inneren Schleife zuweisen.

Probleme erkennen

Wir empfehlen den folgenden Workflow, um Leistungsprobleme zu identifizieren und zu beheben:

  1. Identifizieren und prüfen Sie die folgenden kritischen User Journeys:
    • Gängige Startabläufe, auch über den Launcher und Benachrichtigungen.
    • Bildschirme, auf denen Nutzer durch Daten scrollen.
    • Übergänge zwischen Bildschirmen.
    • Langlaufende Abläufe wie Navigation oder Musikwiedergabe
  2. Prüfen Sie mit folgendem Befehl, was in den vorherigen Abläufen passiert: Debugging-Tools:
    • Perfetto: Damit können Sie sehen, was auf dem gesamten Gerät passiert. mit genauen Zeitdaten.
    • Memory Profiler: Damit können Sie feststellen, welche Arbeitsspeicherzuweisungen erfolgen auf dem Heap.
    • Simpleperf: Zeigt ein Flame-Diagramm dazu an, welche Funktionsaufrufe in einem bestimmten Zeitraum die meiste CPU beanspruchen. Wenn Sie etwas Das dauert in Systrace sehr lange, aber Sie wissen nicht warum, Simpleperf. kann zusätzliche Informationen liefern.

Um diese Leistungsprobleme zu verstehen und zu beheben, ist es wichtig, Fehler in einzelnen Testläufen zu beheben. Sie können die vorherigen Schritte nicht durch folgende Analyse ersetzen: aggregierte Daten. Um jedoch zu verstehen, was Nutzende tatsächlich sehen erkennen, wann Regressionen auftreten können, ist es wichtig, Messwerte einzurichten, bei automatischen Tests und im Praxisbereich:

  • Startvorgänge
  • Ruck
    • Feldmesswerte
      • Play Console-Frame-Vitals: In der Play Console können Sie Messwerte nicht auf einen bestimmten User Journey eingrenzen. Es wird nur die allgemeine Rucklerrate in der App erfasst.
      • Benutzerdefinierte Messung mit FrameMetricsAggregator: Mit FrameMetricsAggregator können Sie Jank-Messwerte während eines bestimmten Workflows erfassen.
    • Labortests
      • Scrollen mit MacroBenchmark:
      • MacroBenchmark erfasst das Frame-Timing mit dumpsys gfxinfo-Befehlen die eine einzelne User Journey einbeziehen. Auf diese Weise können Sie Verzögerung in einer bestimmten User Journey. Die RenderTime-Messwerte, die angeben, wie lange das Zeichnen von Frames dauert, sind wichtiger als die Anzahl der ruckelnden Frames, um Rückschritte oder Verbesserungen zu erkennen.

App-Links sind Deeplinks, die auf Ihrer Website-URL basieren und nachweislich zu Ihrer Website gehören. Im Folgenden sind einige Gründe aufgeführt, die zu fehlgeschlagenen App-Link-Bestätigungen führen können.

  • Intent-Filterbereiche: Fügen Sie autoVerify nur Intent-Filtern für URLs hinzu, auf die Ihre App reagieren kann.
  • Nicht verifizierte Protokoll-Switches: nicht bestätigte Server- und Subdomain-Weiterleitungen als Sicherheitsrisiken gelten und die Prüfung nicht bestehen. Sie sorgen dafür, Fehler bei autoVerify Verknüpfungen. Wenn Sie beispielsweise Links von HTTP zu HTTPS weiterleiten, wie von example.com zu www.example.com, ohne dass die HTTPS-Links überprüft werden, zu einem Fehlschlagen der Überprüfung führen. Bestätigen Sie App-Links, indem Sie einen Intent hinzufügen. Filter.
  • Nicht überprüfbare Links: Wenn Sie nicht überprüfbare Links zu Testzwecken hinzufügen, führen dazu, dass das System die App-Links für Ihre App nicht überprüft.
  • Unzuverlässige Server: Stellen Sie sicher, dass Ihre Server eine Verbindung zu Ihren Client-Apps herstellen können.

App für Leistungsanalysen einrichten

Eine korrekte Einrichtung ist wichtig, damit Sie präzise, wiederholbare und umsetzbare Benchmarks aus einer App. Testen Sie auf einem System, das sich so nah an der Produktion befindet wie während Rauschquellen unterdrückt werden. Die folgenden Abschnitte enthalten eine Anzahl der APK- und systemspezifischen Schritte, die Sie unternehmen können, um eine Testeinrichtung vorzubereiten. von denen einige anwendungsfallspezifisch sind.

Trace-Punkte

Apps können ihren Code mit benutzerdefinierten Trace-Ereignissen instrumentieren.

Während der Erfassung von Traces verursacht das Tracing einen kleinen Overhead von etwa 5 µs pro Abschnitt. Verwenden Sie es also nicht für jede Methode. Wenn Sie größere Arbeitspakete mit einer Dauer von mehr als 0,1 Millisekunden erfassen, können Sie wichtige Erkenntnisse zu Engpässen gewinnen.

Hinweise zu APKs

Debug-Varianten können bei der Fehlerbehebung und Symbolisierung von Stack-Samples hilfreich sein, haben aber schwerwiegende Auswirkungen auf die Leistung. Geräte mit Android 10 (API) ab Level 29) profileable android:shell="true" in ihrem eigenen Manifest, um die Profilerstellung in Release-Builds zu aktivieren.

Verwenden Sie Ihre produktionstaugliche Konfiguration zur Codereduzierung. Je nach Ressourcen, die Ihre App verwendet, kann dies erhebliche Auswirkungen auf die Leistung haben. Einige ProGuard-Konfigurationen werden Tracepunkte entfernt. Sie sollten diese Regeln die Konfiguration, mit der Sie Tests ausführen.

Compilation

Kompiliere deine App auf dem Gerät zu einem bekannten Zustand, in der Regel speed oder speed-profile. JIT-Aktivitäten (Just-in-Time) im Hintergrund können beträchtliche und dies häufig durch eine Neuinstallation des APK zwischen den Testläufen. Dazu können Sie den folgenden Befehl verwenden:

adb shell cmd package compile -m speed -f com.google.packagename

Im speed-Kompilierungsmodus wird die App vollständig kompiliert. Im speed-profile-Modus wird die App gemäß einem Profil der verwendeten Codepfade kompiliert, das während der App-Nutzung erfasst wird. Es kann schwierig sein, Profile einheitlich zu erfassen. und korrekt sind. Wenn Sie sich für einen Einsatz entscheiden, vergewissern Sie sich, dass sie Daten erheben, die Sie erwarten. Die Profile befinden sich an folgendem Ort:

/data/misc/profiles/ref/[package-name]/primary.prof

Mit Macrobenchmark können Sie den Kompilierungsmodus direkt angeben.

Systemanforderungen

Für Low-Level- und High-Fidelity-Messungen müssen Sie Ihre Geräte kalibrieren. A/B ausführen Vergleiche für dasselbe Gerät und dieselbe Betriebssystemversion. Die Leistung kann selbst bei Geräten desselben Typs erheblich variieren.

Auf gerooteten Geräten können Sie für Mikrobenchmarks ein lockClocks-Script verwenden. Diese Skripts haben unter anderem folgende Aufgaben:

  • CPUs auf eine feste Taktfrequenz stellen.
  • Deaktivieren Sie kleine Kerne und konfigurieren Sie die GPU.
  • Energiedrosselung deaktivieren.

Für Tests zur Nutzererfahrung raten wir davon ab, das Skript lockClocks zu verwenden. wie App-Einführung, DoU-Tests und Verzögerungstests. Sie können jedoch für zur Reduzierung von Rauschen in MicroBenchmark-Tests.

Verwenden Sie nach Möglichkeit ein Testframework wie MacroBenchmark, wodurch Rauschen in den Messwerten reduziert und Messungenauigkeiten verhindert werden.

Langsamer App-Start: Unnötige Trampolinaktivität

Eine Trampolinaktivität kann die App-Startzeit unnötig verlängern. Sie sollten daher wissen, ob das bei Ihrer App der Fall ist. Wie im folgenden Beispiel-Trace zu sehen, folgt auf eine activityStart sofort eine weitere activityStart, ohne dass durch die erste Aktivität Frames gerendert werden.

alt_text Abbildung 1: Ein Trace mit Trampolinaktivitäten.

Das kann sowohl am Einstiegspunkt einer Benachrichtigung als auch am Einstiegspunkt eines regulären App-Starts passieren. Sie können das Problem oft durch Refactoring beheben. Wenn Sie zum Beispiel mit dieser Aktivität einrichten, bevor eine andere Aktivität ausgeführt wird. in eine wiederverwendbare Komponente oder Bibliothek übertragen.

Unnötige Zuordnungen, die häufige GCs auslösen

In einem Systrace sehen Sie möglicherweise, dass die automatische Speicherbereinigung häufiger als erwartet erfolgt.

Im folgenden Beispiel ist ein Wert alle 10 Sekunden während eines langwierigen Vorgangs ein Indikator dafür, dass die App möglicherweise unnötig, aber kontinuierlich Speicher zuweist:

Alt-Text Abbildung 2: Ein Trace, das Leerzeichen zwischen GC-Ereignissen zeigt.

Sie werden auch feststellen, dass ein bestimmter Aufrufstack den Großteil der bei Verwendung des Memory Profiler. Sie müssen nicht alle Zuweisungen radikal entfernen, da dies die Wartung des Codes erschweren kann. Konzentrieren Sie sich stattdessen auf Hotspots der Zuweisungen.

Ruckelnde Rahmen

Die Grafikpipeline ist relativ kompliziert und es kann Nuancen bei der um zu ermitteln, ob ein Nutzer einen ausgelassenen Frame sieht. In einigen Fällen kann die Plattform einen Frame mithilfe von Puffern „retten“. Sie können jedoch die meisten um problematische Frames aus der Perspektive Ihrer App zu identifizieren.

Wenn Frames mit wenig Aufwand von der App gezeichnet werden, Choreographer.doFrame() Tracepoints treten in einer Frequenz von 16,7 ms bei 60 fps auf Gerät:

alt_text Abbildung 3: Ein Trace mit häufigen schnellen Frames.

Wenn Sie herauszoomen und durch die Trace navigieren, sehen Sie manchmal, dass Frames einen etwas länger dauern, aber es ist trotzdem in Ordnung, da sie nicht als die zugeteilte Zeit von 16,7 ms zu?

alt_text Abbildung 4 Ein Trace, der häufige schnelle Frames mit periodischen Arbeitsspitzen zeigt.

Wenn diese regelmäßige Kadenz unterbrochen wird, ist das ein ruckelnder Frame, wie in Abbildung 5 dargestellt:

alt_text Abbildung 5 Eine Spur, die einen ruckeligen Frame zeigt.

Sie können üben, sie zu erkennen.

alt_text Abbildung 6: Ein Trace mit mehr ruckeligen Frames.

In einigen Fällen müssen Sie einen Tracepoint heranzoomen, um weitere Informationen welche Aufrufe überhöht werden oder was RecyclerView tut. In anderen Fällen müssen Sie möglicherweise weitere Untersuchungen durchführen.

Weitere Informationen zum Identifizieren von ruckeligen Frames und zum Beheben der Ursachen findest du unter Langsames Rendern.

Häufige RecyclerView-Fehler

Wenn die gesamten Sicherungsdaten von RecyclerView unnötigerweise entwertet werden, zu langen Frame-Renderingzeiten und Verzögerungen führen. Um die Anzahl der Ansichten zu minimieren, die aktualisiert werden müssen, sollten Sie stattdessen nur die Daten ungültig machen, die sich ändern.

Unter Dynamische Daten präsentieren erfahren Sie, wie Sie teure notifyDatasetChanged() vermeiden können. -Aufrufen, die dazu führen, dass Inhalte aktualisiert werden, anstatt sie vollständig zu ersetzen.

Wenn Sie nicht alle verschachtelten RecyclerView-Elemente ordnungsgemäß unterstützen, kann es dazu führen, dass die interne RecyclerView jedes Mal vollständig neu erstellt wird. Für jedes verschachtelte innere RecyclerView muss ein RecycledViewPool festgelegt sein, damit Ansichten zwischen den inneren RecyclerView wiederverwendet werden können.

Wenn nicht genügend Daten oder nicht rechtzeitig vorab abgerufen werden, kann es beim Erreichen des Endes einer scrollbaren Liste zu Rucklern kommen, wenn ein Nutzer auf weitere Daten vom Server warten muss. Technisch gesehen ist das zwar kein Ruckeln, da keine Frame-Deadlines verpasst werden, aber Sie können die UX erheblich verbessern, indem Sie das Timing und die Menge des Prefetching ändern, damit der Nutzer nicht auf Daten warten muss.

App-Fehler beheben

Es gibt verschiedene Methoden, um Fehler in der Leistung Ihrer App zu beheben. Im folgenden Video erhalten Sie einen Überblick über das System-Tracing und die Verwendung des Android Studio-Profilers.

App-Start mit Systrace debuggen

Einen Überblick über den App-Startvorgang erhalten Sie unter App-Startzeit. Siehe Im folgenden Video erhalten Sie einen Überblick über das System-Tracing.

Sie können die Starttypen in den folgenden Phasen unterscheiden:

  • Kaltstart: Es wird ein neuer Prozess ohne gespeicherten Status erstellt.
  • Warmstart: Die Aktivität wird entweder neu erstellt, während der Prozess wiederverwendet wird, oder der Prozess wird mit dem gespeicherten Status neu erstellt.
  • Heißstart: Die Aktivität wird neu gestartet und beginnt bei Inflation.

Wir empfehlen, Systraces mit der System-Tracing-App auf dem Gerät zu erfassen. Verwenden Sie für Android 10 und höher Perfetto. Verwenden Sie für Android 9 und niedriger Systrace. Wir empfehlen außerdem, die Ablaufverfolgungsdateien mit der webbasierten Perfetto Trace Viewer. Weitere Informationen finden Sie unter Übersicht über das System-Tracing.

Achten Sie unter anderem auf Folgendes:

  • Konflikte im Blick behalten: Der Wettbewerb um Monitor-geschützte Ressourcen kann zu deutliche Verzögerung beim App-Start.
  • Synchrone Binder-Transaktionen: Suchen Sie nach unnötigen Transaktionen im kritischen Pfad Ihrer App. Wenn eine notwendige Transaktion teuer ist, sollten Sie in Betracht ziehen, mit dem zugehörigen Plattformteam zusammen, um Verbesserungen vorzunehmen.

  • Gleichzeitige automatische Speicherbereinigung: Dies ist eine häufige und relativ geringe Auswirkung. Wenn Sie jedoch die Probleme auftreten, sollten Sie sich mit dem Android Studio Memory Profiler.

  • E/A: Suchen nach E/A, die während des Starts durchgeführt wurden, und nach langen Wartezeiten.

  • Erhebliche Aktivität in anderen Threads: Diese können den UI-Thread beeinträchtigen, also achten Sie beim Start auf Hintergrundarbeiten.

Wir empfehlen, reportFullyDrawn aufzurufen, wenn der Start aus Sicht der App abgeschlossen ist, um Berichte zu den Startmesswerten der App zu verbessern. Weitere Informationen zur Verwendung von reportFullyDrawn finden Sie im Abschnitt Zeit bis zur vollständigen Anzeige. Sie können über den Perfetto-Trace-Prozessor von RFD definierte Startzeiten extrahieren. Daraufhin wird ein für Nutzer sichtbares Trace-Ereignis ausgegeben.

System-Tracing auf dem Gerät verwenden

Sie können die System-Tracing-App auf Systemebene verwenden, um ein System zu erfassen, auf einem Gerät. Mit dieser App können Sie Traces vom Gerät aufzeichnen, ohne sie an eine Steckdose anschließen oder mit adb verbinden.

Memory Profiler von Android Studio verwenden

Mit dem Memory Profiler von Android Studio können Sie die Arbeitsspeicherauslastung prüfen. Speicherlecks oder schlechten Nutzungsmustern verursacht werden. Sie bietet eine Liveansicht der Objektzuweisungen.

Sie können Speicherprobleme in Ihrer App beheben, indem Sie der Anleitung in der Memory Profiler, um zu verfolgen, warum und wie oft GCs auftreten.

So erstellen Sie ein App-Speicherprofil:

  1. Arbeitsspeicherprobleme erkennen

    Erstellen Sie eine Sitzung zum Erstellen eines Arbeitsspeicherprofils für die User Journey, auf die Sie sich konzentrieren möchten. Achten Sie auf eine zunehmende Objektanzahl, wie in Abbildung 7 dargestellt, die schließlich zu GCs führt, wie in Abbildung 8 dargestellt.

    Alt-Text Abbildung 7: Objektanzahl wird erhöht.

    Alt-Text Abbildung 8 Automatische Speicherbereinigungen

    Nachdem Sie die User Journey identifiziert haben, die zu einer erhöhten Speicherauslastung führt, für die Ursachen der Speicherauslastung.

  2. Diagnose von Hotspots bei Speicherauslastung.

    Wählen Sie einen Bereich in der Zeitachse aus, um sowohl Zuweisungen als auch Größe der flachen Struktur zu visualisieren, wie in Abbildung 9 dargestellt.

    alt_text Abbildung 9. Werte für Allocations und Shallow Größe:

    Es gibt mehrere Möglichkeiten, diese Daten zu sortieren. Im Folgenden finden Sie einige Beispiele für wie Sie mit jeder Ansicht Probleme analysieren können.

    • Nach Klasse sortieren: Hilfreich, wenn Sie Klassen finden möchten, die Objekte generieren, die andernfalls im Cache gespeichert oder aus einem Speicherpool wiederverwendet werden.

      Wenn eine App beispielsweise jede Sekunde 2.000 Objekte der Klasse „Vertex“ erstellt, erhöht sich die Anzahl der Zuweisungen jede Sekunde um 2.000. Dieser Wert wird angezeigt, wenn Sie nach Klasse sortieren. Wenn Sie die einen Speicherpool implementieren, um unnötigen Speicher zu vermeiden.

    • Nach Aufrufstack sortieren: Hilfreich, wenn Sie einen Hotpath finden möchten, in dem Speicher zugewiesen wird, z. B. in einer Schleife oder in einer bestimmten Funktion, die viel Zuweisungsarbeit ausführt.

    • Schlanke Größe: Es wird nur der Arbeitsspeicher des Objekts selbst erfasst. Sie eignet sich zum Erfassen einfacher Klassen, die hauptsächlich aus primitiven Werten bestehen.

    • Beibehaltene Größe: Zeigt den Gesamtarbeitsspeicher aufgrund des Objekts und der Referenzen an. die ausschließlich durch das Objekt referenziert wird. Es ist nützlich, um den Speicherdruck aufgrund komplexer Objekte zu überwachen. Um diesen Wert zu erhalten, erstellen Sie einen vollständigen Speicherdump (siehe Abbildung 10) und fügen Sie die Spalte Retained Size hinzu (siehe Abbildung 11).

      alt_text Abbildung 10: Vollständiger Arbeitsspeicher-Dump.

      Spalte „Beibehaltene Größe“
      Abbildung 11. Spalte „Größe beibehalten“.
  3. Messen Sie die Auswirkungen einer Optimierung.

    GCs sind deutlicher erkennbar und die Auswirkungen des Arbeitsspeichers sind leichter zu messen Optimierungen vor. Wenn durch eine Optimierung die Speicherauslastung reduziert wird, weniger Speicherbereinigungen.

    Um die Auswirkungen der Optimierung zu messen, messen Sie in der Profiler-Zeitachse die Zeit zwischen den Speicherbereinigungen. Sie können sehen, dass es zwischen den GCs länger dauert.

    Die Verbesserungen beim Arbeitsspeicher haben folgende Auswirkungen:

    • Die Wahrscheinlichkeit von Abstürzen aufgrund von fehlendem Arbeitsspeicher wird wahrscheinlich reduziert, wenn die App nicht ständig unter Arbeitsspeicherdruck steht.
    • Weniger GCs verbessern die Verzögerungsmesswerte, insbesondere beim P99. Das liegt daran, dass GCs zu CPU-Konflikten führen, was dazu führen kann, dass Rendering-Aufgaben während der GC verschoben werden.