Profiling mit Instrumenten

Im Enterprise Support Team sehen wir eine Menge iOS-Projekte. Bei der Entwicklung von iOS-Geräten kommt es häufig vor, dass Entwickler ihr Spiel ausführen und sich fragen: "Warum zum Teufel läuft das so langsam?". Es gibt einige großartige Tools für die Leistungsanalyse, und eines der besten ist Instruments. Lesen Sie weiter, um herauszufinden, wie Sie damit Ihre Probleme finden können!
Um Instruments oder eines der Debugging-Tools von XCode zu verwenden, müssen Sie ein Unity-Projekt für das iOS-Build-Target erstellen (wobei die Optionen Development Build und Script Debugging nicht aktiviert sind). Anschließend müssen Sie das resultierende XCode-Projekt mit XCode im Freigabemodus kompilieren und es auf einem angeschlossenen iOS-Gerät bereitstellen.
Nach dem Start von Instruments (entweder durch langes Drücken der Wiedergabetaste oder durch Auswahl von Produkte>Profil) wählen Sie den Time Profiler. Um einen Profilierungslauf zu starten, wählen Sie die erstellte Anwendung in der Anwendungsauswahl aus und drücken Sie dann die rote Schaltfläche Aufzeichnen. Die Anwendung wird auf dem iOS-Gerät mit angeschlossenen Instrumenten gestartet, und der Time Profiler beginnt mit der Aufzeichnung von Telemetriedaten. Die Telemetriedaten werden als blaue Grafik auf der Zeitleiste des Instruments angezeigt.

P.S. Um die Aufrufhierarchie zu bereinigen, klicken Sie auf die Schaltfläche Aufrufstruktur unten links im Detailbereich, um Optionen anzuzeigen, und wählen Sie Rekursion reduzieren und Systembibliotheken ausblenden.

Eine Liste der Methodenaufrufe wird im Detailbereich des Fensters Instrumente angezeigt. Jeder Methodenaufruf der obersten Ebene stellt einen Thread innerhalb der Anwendung dar.
Im Allgemeinen ist die Hauptmethode der Ort, an dem sich alle Hotspots von Interesse befinden, da sie den gesamten verwalteten Code enthält.
Das Erweitern der Hauptmethode ergibt einen tiefen Baum von Methodenaufrufen. Die Hauptverzweigung liegt zwischen zwei Methoden:
- [startUnity] und UnityLoadApplication (Diese Methodennamen erscheinen manchmal in ALL CAPS).
- PlayerLoop
[startUnity] ist von Interesse, da es die gesamte Zeit für die Initialisierung der Unity-Engine enthält. Darunter befindet sich eine Methode namens UnityLoadApplication. Unterhalb von UnityLoadApplication kann die Startzeit profiliert werden.

Sobald Sie einen schönen Zeitabschnitt Ihrer Anwendung profiliert haben, halten Sie den Profiler an und beginnen Sie, den Baum zu erweitern. Wenn Sie sich in der Baumstruktur nach unten arbeiten, werden Sie feststellen, dass die Zeit in ms in der linken Spalte abnimmt. Was Sie suchen, sind Dinge, die eine erhebliche Zeitersparnis bewirken. Dies wird ein Hotspot der Leistung sein. Sobald Sie eine gefunden haben, können Sie zu Ihrer Code-Basis zurückkehren und herausfinden, was da vor sich geht und so viel Zeit in Anspruch nimmt. Es könnte sein, dass es sich um eine absolut notwendige Operation handelt, oder es könnte sein, dass Sie irgendwann in der fernen Vergangenheit einen Vorproduktionscode gehackt haben, der es in Ihr Produktionsprojekt geschafft hat, oder ... nun... es könnte wirklich eine Million Gründe geben. Ob und wie Sie diesen Hotspot beheben, bleibt weitgehend Ihnen überlassen, denn Sie kennen Ihre Codebasis besser als jeder andere :D
Die Instrumente können auch dazu verwendet werden, um nach Leistungseinbußen zu suchen, die weit verteilt sind - solche, die nicht an einem einzigen großen Hotspot auftreten, sondern sich stattdessen als ein paar Millisekunden Zeitverlust an vielen verschiedenen Stellen in einer Codebasis zeigen. Geben Sie dazu entweder einen Teil- oder einen vollständigen Funktionsnamen in das Symbolsuchfeld von Instruments ein, das durch Drücken der Taste ⌘F oder durch Klicken auf Suchen/Suchen... im Menü Bearbeiten angezeigt wird. Wenn Sie ein Profil eines Spielabschnitts erstellen, erweitern Sie PlayerLoop und klappen Sie alle darunter liegenden Methoden aus. Wenn Sie ein Profil der Startzeit erstellen möchten, erweitern Sie UnityLoadApplication und klappen Sie die darunter liegenden Methoden aus. Die Gesamtzahl der Millisekunden, die für einen bestimmten Vorgang verschwendet wurden, kann grob geschätzt werden, indem man die Gesamtzeit betrachtet, die in PlayerLoop oder UnityLoadApplication verbracht wurde, und die Anzahl der Millisekunden in der Spalte self abzieht.
Gemeinsame Methoden, nach denen zu suchen ist:
- "Box(", "box" und "box" - zeigen an, dass C# Value Boxing stattfindet; die meisten Instanzen von Boxing sind trivialerweise festgelegt
- "Concat" - die Verkettung von Zeichenketten lässt sich oft leicht wegoptimieren
- "CreateScriptingArray" - Alle Unity-APIs, die Arrays zurückgeben, weisen neue Kopien von Arrays zu. Minimieren Sie die Aufrufe dieser Methoden.
- "Reflexion" - Reflexion ist langsam. Schätzen Sie auf diese Weise die Zeit, die durch Reflexion verloren geht, und beseitigen Sie sie nach Möglichkeit.
- "FindObjectOfType" - Verwenden Sie dies, um wiederholte oder unnötige Aufrufe von FindObjectOfType oder anderen bekannt langsamen Unity-APIs zu finden.
- "Linq" - Untersuchen Sie die Zeit, die durch das Erstellen und Verwerfen von Linq-Abfragen verloren geht; erwägen Sie, Hotspots durch manuell optimierte Methoden zu ersetzen.
Neben der Erstellung von Profilen für die CPU-Zeit können Sie mit Instruments auch ein Profil der Speichernutzung erstellen. Der Allocations Profiler von Instruments bietet zwei Sonden, die detaillierte Einblicke in die Speichernutzung einer Anwendung ermöglichen. Die Allocations-Probe ermöglicht die Überprüfung der im Speicher befindlichen Objekte während einer bestimmten Zeitspanne. Die VM Tracker-Sonde ermöglicht die Überwachung der Größe des schmutzigen Arbeitsspeichers (Dirty Memory Heap), die von iOS als primäre Metrik verwendet wird, um zu bestimmen, wann eine Anwendung zwangsweise geschlossen werden muss.
Beide Sonden werden gleichzeitig ausgeführt, wenn der Allocations Profiler in Instruments ausgewählt wird. Beginnen Sie einen Profilierungslauf wie üblich durch Drücken der roten Aufnahmetaste.
Um die Zuteilungssonde korrekt einzurichten, müssen Sie sicherstellen, dass die folgenden Einstellungen korrekt sind. Vergewissern Sie sich im unteren Teil des Fensters, dass die Zuweisungsdauer (mittlere Option) auf Angelegt & Dauerhaft eingestellt ist. Vergewissern Sie sich, dass in den Aufzeichnungsoptionen (Menü "Datei") das Kontrollkästchen "Ereignisse bei freiem Speicherplatz verwerfen" aktiviert ist.
Die nützlichste Anzeige zur Untersuchung des Speicherverhaltens ist die Statistikanzeige, die die Standardanzeige bei Verwendung der Allocations Probe ist. Diese Anzeige zeigt eine Zeitleiste an. Bei Verwendung der empfohlenen Einstellungen zeigt das Diagramm blaue Linien an, die den Zeitpunkt und die Größe der derzeit noch aktiven Speicherzuweisungen angeben. Anhand dieses Diagramms können Sie feststellen, ob Speicherplatz verloren gegangen ist, indem Sie das zu testende Szenario einfach wiederholen und sicherstellen, dass keine blauen Linien zwischen den Durchläufen bestehen bleiben.
Eine weitere nützliche Anzeige ist die Anzeige der Anrufbäume. Sie zeigt die Codezeile an, in der die Zuweisungen durchgeführt werden, sowie den Umfang des Speicherverbrauchs, für den die Codezeile verantwortlich ist. Sie können die Anzeige ändern, indem Sie auf die rechte Seite von Details klicken, wie hier gezeigt:

Unten sehen Sie, dass etwa 25 % der gesamten Speichernutzung der getesteten Anwendung allein auf Shader zurückzuführen ist. Da sich die Shader im Lade-Thread befinden, muss es sich um die Standard-Shader handeln, die mit den Standard-Unity-Projekten gebündelt sind, die dann beim Starten der Anwendung geladen werden.

Wenn Sie einen Hotspot identifiziert haben, hängt es nach wie vor ganz von Ihrem Projekt ab, was Sie damit machen.
So, das war's. Ein kurzer Leitfaden zu den Instrumenten. 1000(ish) Wörter und keine Anspielungen auf das A-Team. Wir wollen nicht wieder in Schwierigkeiten geraten wie beim letzten Mal. Urheberrechtsverletzungen sind offiziell nicht lustig™.
Das Enterprise Support-Team erstellt weitere dieser Leitfäden, und wir werden in den kommenden Monaten die vollständigen Versionen unserer Best-Practice-Leitfäden veröffentlichen!
Wir lieben es, wenn ein Plan zustande kommt.
