Mit Profil-GPU-Rendering analysieren

Die <ph type="x-smartling-placeholder"></ph> Das GPU-Rendering-Tool für Profile zeigt die relative Zeit an, die jede Phase mit dem die Rendering-Pipeline den vorherigen Frame rendert. Dieses Wissen können Sie Engpässe in der Pipeline identifizieren, wissen Sie, was optimiert werden muss, um die Rendering-Leistung Ihrer App zu verbessern.

Auf dieser Seite wird kurz erklärt, was in jeder Pipelinephase passiert. die dort zu Engpässen führen können. Vor dem Lesen sollten Sie mit den Informationen auf dieser Seite vertraut sein, Profil-GPU Rendering. Um das Zusammenspiel der einzelnen Phasen zu verstehen, kann es hilfreich sein, <ph type="x-smartling-placeholder"></ph> wie die Rendering-Pipeline funktioniert.

Visuelle Darstellung

Das GPU-Rendering-Tool für Profile zeigt Phasen und ihre relativen Zeiten im eines farbcodierten Histogramms. Abbildung 1 zeigt ein Beispiel für eine wie z. B. ein solches Display.

Abbildung 1: GPU-Rendering-Diagramm für Profil

Jedes Segment jedes vertikalen Balkens, der im Profil-GPU-Rendering angezeigt wird Diagramm stellt eine Phase der Pipeline dar und wird mit einer bestimmten Farbe in das Balkendiagramm an. Abbildung 2 zeigt einen Schlüssel zur Bedeutung der einzelnen angezeigten Farben.

Abbildung 2: Legende des GPU-Renderingdiagramms für Profil

Sobald Sie die Bedeutung jeder Farbe verstanden haben, können Sie bestimmte Aspekte Ihrer um ihre Rendering-Leistung zu optimieren.

Phasen und ihre Bedeutung

In diesem Abschnitt wird erläutert, was in den einzelnen Phasen passiert. auf eine Farbe in Abbildung 2 sowie die Ursachen von Engpässen, auf die Sie achten müssen.

Eingabebehandlung

Die Phase der Eingabeverarbeitung misst, wie lange die App für die Verarbeitung von Eingabeereignissen. Dieser Messwert gibt an, wie lange für die Ausführung von Code benötigt, der als Ergebnis von Eingabeereignis-Callbacks aufgerufen wurde.

Wenn dieses Segment groß ist

Hohe Werte in diesem Bereich sind in der Regel auf zu viel Arbeit zurückzuführen. zu komplexe Arbeit innerhalb der Ereignis-Rückrufe des Eingabe-Handlers. Da diese Callbacks immer im Hauptthread auftreten, die direkte Optimierung der Arbeit oder die Auslagerung einem anderen Thread.

Erwähnenswert ist auch, dass RecyclerView kann Scrollen in dieser Phase auftreten. RecyclerView scrollt, wenn das Touch-Ereignis verarbeitet wird. Daher kann dies dazu führen, dass die Anzahl der Artikel aufgeblasen wird. Aus diesem Grund ist es wichtig, diesen Vorgang so schnell wie möglich machen. Profilerstellungstools wie Traceview oder Systrace kann Ihnen bei der weiteren Untersuchung helfen.

Animation

In der Animationsphase sehen Sie, wie lange es gedauert hat, die in diesem Frame laufen. Die gängigsten Animationskünstler sind ObjectAnimator, ViewPropertyAnimator und Übergänge:

Wenn dieses Segment groß ist

Hohe Werte in diesem Bereich sind in der Regel auf Arbeiten zurückzuführen, die aufgrund von Eigenschaftsänderung der Animation. Zum Beispiel eine Fling-Animation, mit dem Ihr ListView- oder RecyclerView, die Aufrufe und die Bevölkerung stark ansteigen.

Messung/Layout

Damit Android Ihre Ansichtselemente auf dem Bildschirm zeichnen kann, zwei spezifische Vorgänge für Layouts und Ansichten in Ihrer Ansichtshierarchie.

Zunächst misst das System die Ansichtselemente. Jede Ansicht und jedes Layout hat spezifische Daten, die die Größe des Objekts auf dem Bildschirm beschreiben. Einige Ansichten eine bestimmte Größe haben, andere haben eine Größe, die sich an die Größe anpasst, des übergeordneten Layoutcontainers.

Zweitens legt das System die Ansichtselemente fest. Sobald das System die Größen der untergeordneten Elemente kann das System mit Layout, Größenanpassung und die Positionierung der Ansichten auf dem Bildschirm.

Das System führt Messungen und das Layout nicht nur für die zu zeichnenden Ansichten durch, sondern auch für die übergeordneten Hierarchien dieser Datenansichten bis hin zum Stamm Ansicht.

Wenn dieses Segment groß ist

Verbringt eure App pro Frame viel Zeit in diesem Bereich, entweder aufgrund der Menge an Aufrufen, oder Probleme wie <ph type="x-smartling-placeholder"></ph> nicht an der falschen Stelle Hierarchie. In beiden Fällen erfordert die Leistungsoptimierung einen wird verbessert die Leistung Ihrer Ansichtshierarchien.

Code, den Sie onLayout(boolean, int, int, int, int) oder onMeasure(int, int) können sich auch auf die Leistung Probleme. Traceview und Mit Systrace können Sie die Aufrufstacks, um eventuelle Probleme zu identifizieren.

Zeichnen

Der Zeichenbereich übersetzt die Rendering-Vorgänge einer Ansicht, z. B. das Zeichnen. Hintergrund oder Zeichentext in eine Abfolge nativer Zeichenbefehle umzuwandeln. Das System erfasst diese Befehle in einer Anzeigeliste.

In der Draw-Leiste wird angegeben, wie viel Zeit zum Erfassen der Befehle benötigt wird. in die Anzeigeliste für alle Ansichten ein, die auf dem Bildschirm aktualisiert werden mussten. in diesem Frame. Die gemessene Zeit gilt für jeden Code, den Sie der Benutzeroberfläche hinzugefügt haben Objekte in Ihrer App an. Beispiele für solchen Code sind der onDraw(), dispatchDraw(), und die verschiedenen draw ()methods, die zu den Unterklassen der Drawable.

Wenn dieses Segment groß ist

Vereinfacht ausgedrückt können Sie diesen Messwert darstellen, wie lange es dauerte, alle Aufrufe an die onDraw() für jede ungültige Ansicht. Dieses die Zeit, die für die Ausführung von Zeichenbefehlen an Kinder aufgewendet wurde, eventuell vorhandene Drawables. Aus diesem Grund weist der Balken könnte das daran liegen, dass eine Reihe von Aufrufen plötzlich ungültig wurde. Entwertung ist es notwendig, Aufrufe neu zu generieren. Displaylisten anzeigen. Alternativ kann ein kann das Ergebnis einiger benutzerdefinierter Ansichten sein, die äußerst eine komplexe Logik onDraw()-Methoden.

Synchronisieren/Hochladen

Die Synchronisierungs- und Der Uploadmesswert gibt an, wie lange die Übertragung dauert Bitmap-Objekte vom CPU-Speicher zum GPU-Arbeitsspeicher während des aktuellen Frames.

CPU und GPU haben unterschiedliche RAM-Bereiche, da sie unterschiedliche Prozessoren sind die sich der Verarbeitung widmen. Wenn Sie auf Android eine Bitmap zeichnen, überträgt die Bitmap in den GPU-Arbeitsspeicher, bevor die GPU sie in den Bildschirm. Dann speichert die GPU die Bitmap im Cache, sodass das System Daten noch einmal übertragen, es sei denn, die Textur wird aus der GPU-Textur entfernt Cache gespeichert werden.

Hinweis: Auf Lollipop-Geräten ist diese Phase lila.

Wenn dieses Segment groß ist

Alle Ressourcen für einen Frame müssen sich im GPU-Arbeitsspeicher befinden, bevor sie um einen Rahmen zu zeichnen. Das bedeutet, dass ein hoher Wert für diesen Messwert entweder eine große Anzahl kleiner Ressourcenlasten oder eine geringe Anzahl von sehr großen Ressourcen. Ein häufiger Fall ist, wenn eine App eine einzelne Bitmap anzeigt, die an die Bildschirmgröße an. Ein anderer Fall ist, wenn in einer App eine große Anzahl von Miniaturansichten.

Um diese Leiste zu verkleinern, können Sie z. B. folgende Techniken anwenden:

  • Sicherstellen, dass die Bitmap-Auflösungen nicht viel größer sind als die Auflösung angezeigt. Ihre App sollte beispielsweise als 48-x-48-Bild.
  • Vorteile von prepareToDraw() nutzen um vor der nächsten Synchronisierungsphase asynchron eine Bitmap vorab hochzuladen.

Befehle ausgeben

Das Segment Issue Commands (Befehle) stellt die Zeit dar, die benötigt wird, um alle der Befehle, die zum Einzeichnen von Anzeigelisten auf dem Bildschirm erforderlich sind.

Damit das System Anzeigelisten auf dem Bildschirm zeichnen kann, sendet es notwendige Befehle an die GPU senden. Normalerweise führt er diese Aktion über die OpenGL ES API

Dieser Prozess dauert einige Zeit, da das System die letzte Transformation durchführt. und Clipping für jeden Befehl vor dem Senden des Befehls an die GPU. Zusätzliche Informationen entsteht dann auf der GPU-Seite, die die endgültigen Befehle berechnet. Diese enthalten endgültige Transformationen und zusätzliche Begrenzungen.

Wenn dieses Segment groß ist

Die in dieser Phase aufgewendete Zeit ist ein direktes Maß für die Komplexität und Anzahl der Anzeigelisten, die das System in einem bestimmten Frame. Zum Beispiel haben viele Zeichenvorgänge, insbesondere in Fällen, in denen verursacht jedes Zeichenprimitiv einen geringen Preis, das diesmal erhöhen könnte. Beispiel:

Kotlin

for (i in 0 until 1000) {
    canvas.drawPoint()
}

Java

for (int i = 0; i < 1000; i++) {
    canvas.drawPoint()
}

ist wesentlich teurer als:

Kotlin

canvas.drawPoints(thousandPointArray)

Java

canvas.drawPoints(thousandPointArray);

Es gibt nicht immer eine 1:1-Korrelation zwischen ausgebenden Befehlen und tatsächlich Anzeigelisten zeichnen. Im Gegensatz zu Problembefehlen die zum Senden von Zeichenbefehlen an die GPU erfasst, Der Messwert Draw gibt die Zeit an, die zum Erfassen der Ausgabedaten in die Anzeigeliste aufnehmen.

Dieser Unterschied tritt auf, weil die Anzeigelisten wenn möglich an das System gesendet werden. Daher kann es Situationen geben, in denen ein Scrollen, Transformieren oder Animationen aber nicht neu erstellen müssen, erstellen Sie die Zeichnung von Grund auf neu. Dies kann zur Folge haben, dass ohne eine hohe Draw-Befehle-Leiste zu sehen.

Prozess-/Austauschzwischenspeicher

Sobald Android die gesamte Anzeigeliste an die GPU gesendet hat, gibt das System einen letzten Befehl aus, um dem Grafiktreiber mitzuteilen, mit dem aktuellen Frame fertig sind. Jetzt kann der Fahrer Ihren das aktualisierte Bild auf dem Bildschirm.

Wenn dieses Segment groß ist

Es ist wichtig zu verstehen, dass die GPU-Ausführungen parallel CPU Das Android-System gibt Befehle an die GPU aus und geht dann nächste Aufgabe. Die GPU liest diese Zeichenbefehle aus einer Warteschlange und verarbeitet sie. .

In Situationen, in denen die CPU Befehle schneller ausgibt als die GPU verwendet, kann die Kommunikationswarteschlange zwischen den Prozessoren voll. In diesem Fall blockiert die CPU und wartet, bis wieder Platz im um den nächsten Befehl zu platzieren. Dieser Full-Queue-Status tritt häufig während Swap-Puffer ein, da dann ein ganzer Frame Befehle wurden gesendet.

Der Schlüssel zur Bewältigung dieses Problems besteht darin, die Komplexität der auftretenden Arbeiten zu reduzieren. auf der GPU ausführen, ähnlich wie bei den Ausgabebefehlen. .

Sonstiges

Neben der Zeit, die das Renderingsystem für seine Arbeit benötigt, gibt es im Hauptthread einen zusätzlichen Aufwand, nichts mit Rendering zu tun. Die für diese Arbeit verbrauchte Zeit wird gemeldet als sonstige Zeit. „Sonstige Zeit“ steht im Allgemeinen für die Arbeit, im UI-Thread zwischen zwei aufeinanderfolgenden Rendering-Frames.

Wenn dieses Segment groß ist

Ist dieser Wert hoch, enthält Ihre App wahrscheinlich Callbacks, Intents oder die in einem anderen Thread passieren sollten. Tools wie Methode Tracing oder Systrace Einblick in die Aufgaben, die auf dem im Hauptthread. Anhand dieser Informationen können Sie Leistungsverbesserungen gezielter einsetzen.