Leistungsanalyse
Sie haben vielleicht schon vom Performance Analyzer gehört (in Qt Creator 4.6 und früher „CPU Usage Analyzer“ genannt). Es geht um die Profilerstellung von Anwendungen mit dem exzellenten "perf"-Tool in Linux. Sie können es lokal auf Linux - dem grundlegenden Desktop-System - oder auf verschiedenen eingebetteten Geräten verwenden. "perf" kann verschiedene Ereignisse aufzeichnen, die in Ihrer Anwendung auftreten. Dazu gehören Fehler (Verschwendung) im Cache, Speicherlasten, Kontextwechsel oder einer der häufigsten CPU-Zyklen, der regelmäßig ein Stack-Sample schreibt, nachdem eine Reihe von CPU-Zyklen vergangen sind. Das resultierende Profil zeigt, welche Funktionen in Ihrer Anwendung die meisten CPU-Zyklen beanspruchen. Dies ist zumindest bisher die prominenteste Verwendung des Performance Analyzer.
Ablaufverfolgungspunkte erstellen
Mit Qt Creator 4.7 können Sie auch Ereignisse für Ablaufverfolgungspunkte protokollieren, und wenn Ihre Ablaufverfolgungspunkte eine bestimmte Benennungsbedingung erfüllen, erkennt Qt Creator, dass sie Ressourcen zuweisen oder diese Ressourcen freigeben. Daher können Sie Ihre Anwendungen auf vielfältige Weise überwachen, indem Sie Tracepoints auf malloc, free und friends setzen. Um Ihnen beim Einrichten von Ablaufverfolgungspunkten für diesen Anwendungsfall zu helfen, verpackt Qt Creator ein Shell-Skript (Shell-Skript), das Sie ausführen können, und fordert Sie auf, es auszuführen. Öffnen Sie zunächst Ihr Projekt und wählen Sie die Laufkonfiguration aus, die Sie untersuchen möchten. Wählen Sie dann einfach die Schaltfläche "Generate Tracepoints ..." in der Titelleiste des Analysers und Sie erhalten:
Wie es funktioniert?
Damit unprivilegierte Benutzer Tracepoints verwenden können, muss das Skript die Debugging-Engine und Dateisystem-Traces für alle Benutzer auf dem System verfügbar machen. Sie sollten dies nur in kontrollierten Umgebungen tun. Das Skript funktioniert normalerweise für 32-Bit-ARM-Systeme und 64-Bit-x86-Systeme. 64-Bit-ARM-Systeme können Tracepoints nur akzeptieren, wenn Sie die Linux-Kernel-Version 4.10 oder höher ausführen. Um Ablaufverfolgungspunkte auf x86-32-Bit-Systemen festzulegen, benötigen Sie die Debug-Symbole für Ihre Standard-C-Bibliothek. Das Skript versucht, Ablaufverfolgungspunkte für jeden binären (binären) Code namens libc.so.6 zu erstellen, der in /lib gefunden wird. Wenn Sie ein 64-Bit-System mit zusätzlichen 32-Bit-Bibliotheken installiert haben, wird es versuchen, Ablaufverfolgungspunkte für beide Unterstrukturen zu erstellen. Es kann nur für einen von ihnen erfolgreich sein. Dies ist kein Problem, wenn Ihre Anwendung auf eine Unterstruktur abzielt, für die das Skript Ablaufverfolgungspunkte setzen konnte.
Fehlerbehebung
Wenn das Point-Trace-Skript fehlschlägt, können Sie überprüfen, ob Ihr Kernel mit aktivierter Option CONFIG_UPROBE_EVENT kompiliert wurde. Ohne diese Option unterstützt der Kernel keine Benutzer-Tracepoints. Alle 32-Bit-ARM-Images, die mit Qt for Device Creation ausgeliefert werden, verfügen seit Version 5.11 über diese Option. Die meisten Linux-Distributionen, die für die Desktop-Nutzung entwickelt wurden, verwenden standardmäßig CONFIG_UPROBE_EVENT.
Verwenden von Ablaufverfolgungspunkten für die Profilerstellung
Nachdem Sie Ablaufverfolgungspunkte erstellt haben, müssen Sie Qt Creator anweisen, sie für die Profilerstellung zu verwenden. Dazu gibt es in den Performance-Analyzer-Einstellungen eine praktische Tastenkombination. Sie können auf die Einstellungen entweder für Ihr spezifisches Projekt in den "Ausführen"-Einstellungen im Projektmodus oder global über "Optionen" im Menü "Extras" zugreifen. Wählen Sie einfach "Trace-Punkte verwenden". Qt Creator ersetzt dann Ihre aktuelle Ereigniskonfiguration durch alle Tracepoints, die es auf dem Zielsystem findet, und stellt sicher, dass jedes Mal, wenn ein Tracepoint gefunden wird, ein Muster geschrieben wird.
Danach müssen Sie auf die Start-Schaltfläche in der Profiler-Symbolleiste klicken, um die Anwendung zu profilieren. Nachdem die Anwendung beendet ist, sammelt Qt Creator die Profildaten und zeigt sie an.
Dateninterpretation
Der einfachste Weg, um herauszufinden, welche Teile des Codes viel Speicher verwenden, besteht darin, sich das Flame-Diagramm anzusehen. Um die aussagekräftigsten Ergebnisse zu erhalten, wählen Sie den Modus „Spitzenverbrauch“ in der oberen rechten Ecke. Dies zeigt Ihnen das angegebene Diagramm, sortiert nach der kumulierten Menge an Speicher, die von diesen Aufrufketten zugewiesen wurde. Betrachten Sie dieses Beispiel
Ergebnisse
Wie Sie hier sehen können, ist dies ein Qt Creator-Profil, das einen großen QML-Trace in QML Profiler lädt. Der QML-Profiler verwendet viel Speicher, wenn große Ablaufverfolgungen angezeigt werden. Dieses Profil teilt uns einige Nutzungsdetails mit. Übrigens sagt uns diese feurige Grafik Folgendes:
- Modelle für Zeitleiste, Statistiken und Flammendiagramme verbrauchen etwa 43 % des Spitzenspeichers. TimelineTraceManager::appendEvent(...) sendet Ereignisse an verschiedene Modelle und bewirkt eine Auswahl.
- Davon entfällt mit 18,9 % der größte Anteil auf die Modelle der Timeline-Reihe. Die Kategorien JavaScript, Bindings und Signal Handling sind Bereichsmodelle. Sie speichern einen Vektor zusätzlicher Daten mit einem Datensatz für jeden solchen Bereich. Sie können QArrayData::allocate(...) sehen, das Speicher für diese Vektoren zuweist.
- Das Timeline-Rendering verbraucht den größten Teil des Speichers, der nicht den Basismodellen zugewiesen ist. Insbesondere erscheint Timeline::NodeUpdater::run() in allen anderen Stacktraces. Diese Funktion ist für das Ausfüllen der Geometrie verantwortlich, die zum Anzeigen der Timeline-Kategorien verwendet wird. Daher sehen wir QSGGeometry::allocate(...) als direkten Grund für Zuweisungen. Es sagt uns auch, warum QML eine Grafikkarte mit mehreren Gigabyte Speicher profiliert, um solche Spuren anzuzeigen.
Mögliche Optimierungen
Von hier aus ist es einfach, Ideen zur Optimierung von Störfunktionen vorzuschlagen. Wir könnten noch einmal überdenken, ob wir wirklich alle Daten brauchen, die in den verschiedenen Modellen gespeichert sind, oder ob wir sie vorübergehend auf der Festplatte speichern, bis wir sie brauchen. Die überwältigende Menge an Geometrie, die hier hervorgehoben wird, deutet auch darauf hin, dass die Schwelle zum Zusammenführen benachbarter Ereignisse zu einer dichten Spur möglicherweise zu niedrig ist. Schließlich könnten wir die Geometrie im Hauptspeicher freigeben, sobald wir sie auf die GPU laden.
Tracing-Overhead
Das Profilieren jedes Aufrufs von malloc() und free() in einer Anwendung führt zu erheblichem Overhead. Der Kern wird höchstwahrscheinlich nicht mit der Zeit gehen können und daher einige Samples fallen lassen. Abhängig von Ihrer spezifischen Arbeitsbelastung kann Ihnen das resultierende Profil jedoch dennoch wichtige Informationen liefern. Mit anderen Worten: Wenn Ihre Anwendung in nur wenigen Aufrufen von malloc() eine große Menge Speicher zuweist und gleichzeitig eine kleine Menge mit hoher Frequenz zuweist und freigibt, verpassen Sie möglicherweise die Aufrufe von malloc(), an denen Sie interessiert sind weil der Kernel sie verwerfen kann. Wenn jedoch problematische malloc()-Aufrufe einen größeren Prozentsatz der Gesamtaufrufe ausmachen, werden Sie wahrscheinlich zumindest einige davon abfangen. In beiden Fällen zeigt Ihnen Qt Creator absolute Zahlen für die Zuweisung, Freigabe und maximale Speichernutzung an. Diese Zahlen beziehen sich auf die tatsächlich gemeldeten Perf-Samples und sind daher nicht ganz genau. Andere Tools melden andere Zahlen.
Spezielle Speicherzuweisungsfunktionen
Außerdem gibt es Speicherzuweisungsfunktionen, mit denen Sie auf diese Weise kein Profil erstellen können. Insbesondere gibt posix_memalign() den resultierenden Exponenten nicht auf dem Stack oder in einem Register zurück. Daher können wir es nicht mit einem Tracepoint schreiben. Außerdem werden benutzerdefinierte Speicherzuweisungen, die Sie möglicherweise für Ihre Anwendung verwenden, nicht von den Standardablaufverfolgungspunkten verarbeitet. Beispielsweise wird der von QML verwendete JavaScript-Heap-Allokator nicht im Profil angezeigt. Für diesen speziellen Fall können Sie jedoch QML Profiler verwenden. Es gibt auch verschiedene Ersetzungen für die standardmäßigen C-Zuweisungsfunktionen, wie etwa jemalloc oder tcmalloc. Wenn Sie sie verfolgen möchten, müssen Sie benutzerdefinierte Ablaufverfolgungspunkte definieren
Fazit
Die Erstellung von Speichernutzungsprofilen mit dem Qt Creator Performance Analyzer ist eine schnelle und einfache Möglichkeit, wichtige Informationen über die Speichernutzung Ihrer Anwendung zu erhalten. Es funktioniert in einer Box für alle Linux-Ziele, die von Qt Creator unterstützt werden. Sie können die erhaltenen Profildaten ohne weitere Verarbeitung oder Übermittlung von Daten sofort in einer öffentlichen grafischen Benutzeroberfläche (GUI) einsehen. Andere Tools können genauere Daten liefern. Für einen schnellen Überblick über die Speichernutzung Ihrer Anwendung ist Performance Analyzer jedoch oft das beste Werkzeug.