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.
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.
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.