Das Flutter-Framework funktioniert standardmäßig einwandfrei und schnell. Bedeutet dies jedoch, dass Sie überhaupt nicht an die Leistung denken müssen? Nein. Es ist absolut real, Flutter-Anwendungen zu schreiben, die langsam sind. Auf der anderen Seite können Sie das Framework auch maximal nutzen und Ihre Anwendungen nicht nur schnell, sondern auch effizient gestalten und weniger Prozessor- und Batteriezeit verbrauchen.

Dies möchten wir sehen: ein statistisch signifikantes Ergebnis des Vergleichs zweier Versionen Ihrer Anwendung anhand einer signifikanten Metrik. Lesen Sie weiter, um herauszufinden, wie.
Es gibt einige allgemeine Richtlinien zur Leistungsoptimierung in Flutter:
- Aktivieren Sie beim Aktualisieren des Status so wenige Widgets wie möglich.
- Aktualisieren Sie den Status nur bei Bedarf.
- Nehmen Sie rechenintensive Aufgaben aus Ihren
build
und idealerweise aus dem Hauptisolat heraus.
Die traurige Wahrheit ist, dass bei vielen Fragen zur Leistungsoptimierung die Antwort "wie viel Glück" lautet. Ist diese spezielle Optimierung den Aufwand und die Wartungskosten für dieses spezielle Widget wert? Ist dieser spezielle Ansatz in dieser speziellen Situation sinnvoll?
Die einzig nützliche Antwort auf diese Fragen ist das Testen und Messen. Quantifizieren Sie, wie sich jede Auswahl auf die Leistung auswirkt, und treffen Sie Entscheidungen basierend auf diesen Daten.
Die gute Nachricht ist, dass Flutter großartige Tools zur Leistungsprofilerstellung wie Dart DevTools (derzeit in der Vorschau-Version) bereitstellt , einschließlich des Flutter Inspector, oder Sie können den Flutter Inspector direkt in Android Studio verwenden (mit installiertem Flutter-Plugin). Sie haben einen Flutter Driver
zum Testen Ihrer Anwendung und des Profile mode
, um Leistungsinformationen zu speichern.
Die schlechte Nachricht ist, dass moderne Smartphones zu intelligent sind.
Das Problem mit den Regulierungsbehörden
Die Quantifizierung der Leistung von Flutter-Anwendungen ist für iOS- und Android-Controller besonders schwierig. Diese Daemons auf Systemebene steuern die Geschwindigkeit der Zentral- und Grafikprozessoren abhängig von der Last. Grundsätzlich ist dies natürlich gut, da es einen reibungslosen Betrieb bei geringerem Batterieverbrauch bietet.
Der Nachteil ist, dass Sie Ihre Anwendung viel schneller gestalten können, indem Sie den Arbeitsaufwand erhöhen.
Unten sehen Sie, wie der Regler durch Hinzufügen eines Zyklus bedeutungsloser Druckaufrufe zur Anwendung die CPU auf eine erhöhte Frequenz umschaltete, wodurch die Anwendung viel schneller und ihre Leistung vorhersehbarer wurde.

Das Problem mit den Regulierungsbehörden: Standardmäßig können Sie Ihren Nummern nicht vertrauen. In diesem Span-Diagramm haben wir separate Läufe auf der x-Achse (gekennzeichnet durch die genaue Startzeit) und die Erstellungszeit auf der Y-Achse. Wie Sie sehen, führt die Einführung einiger völlig unnötiger Druckanweisungen dazu, dass die Erstellungszeit abnimmt aber nicht auf.
In diesem Experiment führte der schlechteste Code zu einer schnelleren Erstellungszeit (siehe oben), einer schnelleren Rasterzeit und einer höheren Bildrate. Wenn objektiv schlechterer Code zu verbesserten Leistungsindikatoren führt, können Sie sich nicht auf diese Indikatoren als Leitfaden (Empfehlung) verlassen.
Dies ist nur ein Beispiel dafür, wie die Leistungstests für mobile Apps nicht intuitiv und komplex sein können.
Im Folgenden teile ich einige der Tipps, die ich bei der Arbeit an Flatters Developer Quest- Anwendung für Google I / O gesammelt habe.
Allgemeine Tipps
- Messen Sie die Leistung nicht im Debug-Modus (
DEBUG mode
). Messen Sie die Leistung nur im Profile mode
. - Messen Sie auf einem realen Gerät, nicht auf iOS Simulator oder Android Emulator. Software-Emulatoren eignen sich hervorragend für die Entwicklung, weisen jedoch andere Leistungsmerkmale als echte auf. Mit Flutter können Sie auf einem simulierten Gerät nicht im Profilierungsmodus arbeiten, da dies keinen Sinn ergibt. Die Daten, die Sie auf diese Weise erfassen, gelten nicht für die tatsächliche Leistung.
- Verwenden Sie im Idealfall genau dasselbe physische Gerät. Machen Sie es zu Ihrem dedizierten Leistungstestgerät und verwenden Sie es niemals für andere Zwecke.
- Entdecken Sie die Tools zur Erstellung von Flatterleistungsprofilen .
CPU / GPU-Regler
Wie oben erläutert, ändern moderne Betriebssysteme die Frequenz jedes Prozessors und jeder GPU, die ihnen zur Verfügung stehen, entsprechend der Last und einigen anderen Heuristiken. (Wenn Sie beispielsweise den Bildschirm berühren, wird normalerweise die Geschwindigkeit Ihres Android-Telefons erhöht.)
Unter Android können Sie diese Steuerelemente deaktivieren. Wir nennen diesen Prozess "Skalierungssperre".
- Erstellen Sie ein Skript, das die Steuerelemente auf Ihrem Gerät deaktiviert, um die Leistung zu testen. Sie können das Skia-Beispiel als Inspiration verwenden. Sie können auch die Unix-CPU-API überprüfen.
- Vielleicht möchten Sie etwas weniger Vielseitiges und Leichteres, wenn Sie nicht so viel Testarbeit leisten wie Skia. Überprüfen Sie das Shell-Skript in Developer Quest, um zu sehen, wohin Sie gehen müssen. Im nächsten Teil des Skripts wird beispielsweise die CPU für den Userspace-Controller festgelegt (der einzige Controller, der die Prozessorfrequenz selbst nicht ändert).
- Ihr Ziel ist es hier nicht, die tatsächliche Leistung zu simulieren (Benutzer schalten die Regler auf ihren Geräten nicht aus), sondern zwischen den Starts vergleichbare Leistungsindikatoren zu haben.
- Am Ende müssen Sie experimentieren und das Shell-Skript an das Gerät anpassen, das Sie verwenden werden. Dies funktioniert, aber bis Sie dies tun, werden Sie Ihre Leistungsdaten austricksen.

Eine frühe Version von Developer Quest, die mit dem Flutter-Treiber auf meinem Desktop getestet wurde.
Flattertreiber
Mit dem Flattertreiber können Sie Ihre Anwendung automatisch testen. Lesen Sie den Abschnitt „Leistungsprofilerstellung“ auf flutter.dev, um herauszufinden, wie Sie ihn beim Profilieren Ihrer Anwendung verwenden können.
- Testen Sie Ihre Anwendung nicht manuell, um die Leistung zu testen. Verwenden Sie immer den Flattertreiber, um wirklich aussagekräftige Daten zu erhalten.
- Schreiben Sie Ihren Flutter-Treibercode so, dass überprüft wird, was Sie wirklich messen möchten. Wenn Sie eine allgemeine Anwendungsleistung benötigen, gehen Sie alle Teile der Anwendung durch und tun Sie, was der Benutzer tun würde.
- Wenn Ihre Anwendung ein
Random
Element aufweist (Zufall, Netzwerkereignisse usw.), erstellen Sie für solche Situationen ein "Mock". Testläufe sollten so nah wie möglich beieinander liegen. - Wenn Sie möchten, können Sie der Timeline mithilfe der
startSync()
und finishSync()
der Timeline- Klasse benutzerdefinierte Ereignisse hinzufügen. Dies kann nützlich sein, wenn Sie an der Ausführung einer bestimmten Funktion interessiert sind. Setzen Sie startSync()
an den Anfang und finishSync()
an das Ende. - Speichern Sie sowohl die Zusammenfassung ( writeSummaryToFile ) als auch, was noch wichtiger ist, die Rohzeitleiste ( writeTimelineToFile ).
- Testen Sie jede Version Ihrer Anwendung mehrmals. Für Developer Quest habe ich 100 Starts ausgegeben. (Wenn Sie Dinge messen, die möglicherweise verrauscht sind, z. B. die Verwendung der p99-Metrik, benötigen Sie möglicherweise viel mehr Läufe.) Für POSIX-basierte Systeme bedeutet dies einfach Folgendes:
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
.

Das Timeline-Tool von Chrome zum Überprüfen der Profilerstellungsergebnisse in Flutter.
Zeitleiste
Die Zeitleiste ist die Rohausgabe Ihrer Profilerstellungsergebnisse. Flutter schreibt diese Informationen in eine JSON-Datei, die in chrome://tracing
heruntergeladen werden kann.
- Erfahren Sie, wie Sie die vollständige Zeitleiste in Chrome öffnen. Sie öffnen einfach
chrome://tracing
im Chrome-Browser, klicken auf "Load" und wählen die JSON-Datei aus. Sie können mehr in dieser kurzen Anleitung lesen. (Es gibt auch ein Flutter-Timeline-Tool , das sich derzeit in der technischen Vorschau befindet. Ich habe es nicht verwendet, da das Developer Quest-Projekt gestartet wurde, bevor die Flutter-Tools bereit waren.) - Verwenden Sie die WSAD-Tasten, um in
chrome://tracing
die Timeline zu navigieren chrome://tracing
und 1234, um die Betriebsmodi zu ändern. - Wenn Sie Leistungstests zum ersten Mal einrichten, sollten Sie Flutter Driver mit dem Android-Tool Systrace ausführen. Auf diese Weise erhalten Sie eine bessere Vorstellung davon, was tatsächlich im Gerät vor sich geht, einschließlich Informationen zur Skalierung der Prozessorfrequenz. Messen Sie nicht die gesamte Anwendung mit Systrace, da dies alles langsamer und weniger vorhersehbar macht.
- Wie starte ich Android Systrace mit Flutter Driver? Starten Sie zunächst Android Systrace mit
/path/to/your/android/sdk/platform-tools/systrace/systrace.py --atrace-categories=gfx,input,view,webview,wm,am,sm,audio,video,camera,hal,app,res,dalvik,rs,bionic,power,pm,ss,database,network,adb,pdx,sched,irq,freq,idle,disk,load,workq,memreclaim,regulators,binder_driver,binder_lock
. flutter run test_driver/perf.dart --profile --trace-systrace
Anwendung flutter run test_driver/perf.dart --profile --trace-systrace
. flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/
(wobei NNNNN der Port ist, über den Sie die obige Flatteranwendung erhalten).
Metriken
Es ist besser, so viele Metriken wie möglich zu betrachten, aber ich habe entschieden, dass einige nützlicher sind als andere.
Die Erstellungszeit und die Rasterzeit (Metriken, die standardmäßig mit TimelineSummary
bereitgestellt werden) sind nur für wirklich harte Leistungstests nützlich, die nur das Erstellen einer Benutzeroberfläche umfassen.
Betrachten Sie TimelineSummary.frameCount
als eine Möglichkeit, Bilder pro Sekunde (FPS) zu berechnen. Flatter-Profiling-Tools liefern keine echten Bildrateninformationen. TimelineSummary
stellt die countFrames()
-Methode countFrames()
, zählt jedoch nur die Anzahl der abgeschlossenen Frame-Assemblys. Eine gut optimierte Anwendung, die unnötige Neuerstellungen (Updates) begrenzt, hat niedrigere FPS als eine nicht optimierte Anwendung, die häufig neu erstellt wird.
Persönlich erhalte ich die nützlichsten Daten, indem ich die gesamte Prozessorzeit messe, die für die Ausführung des Dart-Codes aufgewendet wurde. Dies zählt den Code, der sowohl in Ihren build
Methoden als auch außerhalb ausgeführt wird. Angenommen, Sie führen Profiling-Tests auf einem Gerät mit skalierter Sperre durch, kann die Gesamt-CPU-Zeit als eine gute Annäherung an den Batterieverbrauch Ihrer Anwendung angesehen werden.

Der einfachste Weg, um die gesamte Prozessorzeit zu ermitteln, die für die Ausführung von Dart-Code aufgewendet wurde, besteht darin, die Anzahl der MessageLoop:FlushTasks
Ereignisse auf der Zeitachse zu schätzen. Für Developer Quest habe ich ein Dart-Tool geschrieben , um sie zu extrahieren.
Suchen Sie nach Extremen, um Junk (Papierkorb) (dh abgelegte Frames) zu finden. Für einen bestimmten Fall von Developer Quest und das Gerät, auf dem wir getestet haben, ist es beispielsweise hilfreich, die Erstellungszeit des 95. Perzentils zu betrachten. (Die Erstellungszeit des 90. Perzentils war zu ähnlich, selbst wenn Sie den Code mit völlig unterschiedlichen Leistungsstufen vergleichen und die Zahlen des 99. Perzentils normalerweise verrauscht sind. Ihre Leistung kann variieren.)

Testen Sie, wie oben erwähnt, jede Version Ihrer Anwendung mehrmals (möglicherweise 100). Verwenden Sie dann Durchschnitts- oder Perzentildaten mit Fehlerfeldern. Besser noch, verwenden Sie Span-Diagramme.
Ergebnisse
Nach dem Einstellen können Sie Commits sicher vergleichen und Experimente durchführen. Unten sehen Sie die Antwort auf ein allgemeines Dilemma: "Lohnt sich diese Optimierung der Wartungskosten?"

Ich denke, dass in diesem speziellen Fall die Antwort ja ist. Dank nur wenigen Codezeilen benötigt jede automatisierte Passage unserer Anwendung durchschnittlich 12% weniger CPU-Zeit.
Aber - und das ist die Hauptbotschaft dieses Artikels - die Messungen einer anderen Optimierung können etwas völlig anderes zeigen. Es ist verlockend, aber falsch zu versuchen, eine Leistungsmessung zu weit zu extrapolieren.
Mit anderen Worten: "Wie viel Glück." Und wir müssen uns damit abfinden.