Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Leistungsprofilierung ist der Prozess der Messung der Leistung einer Anwendung, um Bereiche zur Verbesserung zu identifizieren. .NET MAUI und Clientanwendungen interessieren sich im Allgemeinen für:
- Startzeit: Die Zeit, die die Anwendung benötigt, um den ersten Bildschirm zu starten und anzuzeigen.
- CPU-Auslastung: Wenn bestimmte Methoden zu viel CPU-Zeit in Anspruch nehmen: entweder über viele Aufrufe oder lange Ausgeführte Vorgänge.
- Speicherauslastung: Wenn viele Zuordnungen außerhalb des Grunds erfolgen oder Speicherverluste auftreten.
Die Techniken und Tools zur Verbesserung dieser Metriken sind unterschiedlich, was wir in diesem Leitfaden aufklären möchten. Die Tools, die zum Profilieren von .NET MAUI-Anwendungen verwendet werden, können auch je nach Plattform variieren. In diesem Leitfaden werden Android-, iOS-, Mac Catalyst- und Windows-Profilerstellungsansätze behandelt.
Von Bedeutung
Profilieren Sie stets Ihre Builds Release, um genaue Leistungsmessungen zu erhalten.
Debug-Builds verwenden den Interpreter (UseInterpreter=true), um die C#-Hot-Reload-Unterstützung bereitzustellen, was die Leistung erheblich beeinträchtigt und zu unrealistischen Ergebnissen führt.
Voraussetzungen
Installieren von Diagnosetools
Um .NET MAUI-Anwendungen unter iOS und Android zu profilieren, müssen Sie die folgenden globalen .NET-Tools installieren:
-
dotnet-trace– Erfasst CPU-Ablaufverfolgungen und Leistungsdaten -
dotnet-dsrouter– Leitet Diagnoseverbindungen von Remotegeräten an Ihren lokalen Computer weiter. -
dotnet-gcdump– Sammelt Speicherabbilder zur Analyse der verwalteten Speicherauslastung.
Sie können diese Tools mit den folgenden Befehlen installieren:
$ dotnet tool install -g dotnet-trace
You can invoke the tool using the following command: dotnet-trace
Tool 'dotnet-trace' was successfully installed.
$ dotnet tool install -g dotnet-dsrouter
You can invoke the tool using the following command: dotnet-dsrouter
Tool 'dotnet-dsrouter' was successfully installed.
$ dotnet tool install -g dotnet-gcdump
You can invoke the tool using the following command: dotnet-gcdump
Tool 'dotnet-gcdump' was successfully installed.
Hinweis
Sie benötigen mindestens Version 9.0.652701 aller Diagnosetools, um die in diesem Handbuch beschriebenen Features zu verwenden. Überprüfen Sie dotnet-trace, dotnet-dsrouter und dotnet-gcdump auf NuGet für die neuesten Versionen.
Ab Version 9.0.652701 enthalten sowohl dotnet-trace als auch dotnet-gcdump eine --dsrouter Option, die dotnet-dsrouter automatisch als Unterprozess startet und verwaltet. Dadurch entfällt die Notwendigkeit, dotnet-dsrouter separat auszuführen, was den Profilerstellungsworkflow erheblich vereinfacht.
Eine Live-Demo zur Verwendung dieser Tools finden Sie in der .NET Conf-Sitzung ,.NET Diagnostic Tooling with AI".
Wie die Tools zusammenarbeiten
Um diese Diagnosetools unter iOS und Android zu verwenden, arbeiten mehrere Komponenten zusammen:
- Die globalen .NET-Tools (
dotnet-trace,dotnet-gcdump,dotnet-dsrouter) werden auf Ihrem Entwicklungscomputer ausgeführt. - Die Mono-Diagnosekomponente (
libmono-component-diagnostics_tracing.so) ist in Ihrem Anwendungspaket enthalten. -
dotnet-dsrouterleitet die Diagnoseverbindung vom Remotegerät oder Emulator an einen lokalen Port auf Ihrem Computer weiter. - Die Diagnosetools stellen eine Verbindung mit diesem lokalen Port her, um Profilerstellungsdaten zu sammeln.
Die --dsrouter Option in dotnet-trace und in dotnet-gcdump behandelt automatisch die Komplexität des Startens von dotnet-dsrouter und Koordinierens der Verbindung.
Erstellen Ihrer Anwendung für Profilerstellung
Zum Aktivieren der Profilerstellung muss Ihre Anwendung mit speziellen MSBuild-Eigenschaften erstellt werden, die die Diagnosekomponenten enthalten und die Verbindung mit den Profilerstellungstools konfigurieren.
Grundlegendes zu Diagnoseeigenschaften
Die folgenden MSBuild-Eigenschaften steuern, wie Ihre Anwendung mit den Diagnosetools kommuniziert:
DiagnosticAddress: Die IP-Adresse, an derdotnet-dsrouterlauscht. Verwenden Sie10.0.2.2für Android-Emulatoren (dies ist die Loopback-Adresse des Hostcomputers aus der Perspektive des Emulators) und127.0.0.1für physische Geräte und iOS.DiagnosticPort: Die Portnummer für die Diagnoseverbindung (Standardeinstellung ist9000).DiagnosticSuspend: Wenntruedie Anwendung wartet, bis der Profiler eine Verbindung herstellt, bevor sie gestartet wird. Sobaldfalsedie Anwendung startet, kann der Profiler später eine Verbindung herstellen. Verwenden Sietruefür die Startprofilerstellung undfalsefür die Laufzeitprofilerstellung und Speicherabbilder.DiagnosticListenMode: Wird aufconnectfür Android festgelegt (die App stellt eine Verbindung zudotnet-dsrouterher), oder auflistenfür iOS (die App wartet darauf, dassdotnet-dsroutereine Verbindung herstellt).EnableDiagnostics: Wenntruevorhanden ist, wird die Mono-Diagnosekomponente in das Anwendungspaket aufgenommen. Dies wird implizit festgelegt, wenn Sie eine derDiagnostic*MSBuild-Eigenschaften festlegen. Diese Eigenschaft funktioniert unter Android, iOS und Mac Catalyst.
Hinweis
Bei Verwendung von CoreCLR (derzeit experimentell unter Android mit geplanter iOS-Unterstützung) ist die Diagnosekomponente in die Laufzeit integriert und EnableDiagnostics nicht erforderlich.
Befehlsbeispiele für Build
Wenn Sie dotnet-trace oder dotnet-gcdump mit der --dsrouter-Option ausführen, zeigt das Tool Anweisungen zum Erstellen Ihrer Anwendung an.
Beispiel:
Für Android-Emulatoren:
dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=10.0.2.2 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=false -p:DiagnosticListenMode=connect
Für Android-Geräte:
dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=false -p:DiagnosticListenMode=connect
Für iOS-Geräte und Simulatoren:
dotnet build -t:Run -c Release -f net10.0-ios -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=false -p:DiagnosticListenMode=listen
Hinweis
Verwenden Sie -f net10.0-android oder -f net10.0-ios für Projekte mit mehreren Zielframeworks in $(TargetFrameworks).
Von Bedeutung
Anwendungen, die mit diesen Diagnoseeigenschaften erstellt wurden, sollten nur für Entwicklung und Tests verwendet werden. Veröffentlichen Sie niemals Builds mit Diagnosekomponenten, die für die Produktion aktiviert sind, da sie Endpunkte mit tieferen Einblicken in den Code Ihrer Anwendung verfügbar machen können.
Profilierung der CPU-Auslastung
Das dotnet-trace Tool sammelt CPU-Samplinginformationen in Formaten wie .nettrace und .speedscope.json. Diese Ablaufverfolgungen zeigen Ihnen die für jede Methode aufgewendete Zeit, um Leistungsengpässe in Ihrer Anwendung zu identifizieren.
Der Workflow für die CPU-Profilerstellung hängt davon ab, ob Sie startzeit- oder Profilerstellungs-Laufzeitvorgänge messen. Der Hauptunterschied ist die -p:DiagnosticSuspend MSBuild-Eigenschaft.
Profilerstellungsstartzeit
Um genaue Startzeitmessungen zu erfassen, pausieren Sie den Start der Anwendung, bis der Profiler bereit ist. Dadurch wird sichergestellt, dass Sie die gesamte Startsequenz von Anfang an erfassen.
Öffnen Sie ein Terminal und beginnen Sie
dotnet-tracemit der Option--dsrouter.dotnet-trace collect --dsrouter android-emu --format speedscopeOder für ein physisches Android-Gerät:
dotnet-trace collect --dsrouter android --format speedscopeVerwenden Sie
--dsrouter iosfür iOS-Geräte und--dsrouter ios-simfür Simulatoren.Erstellen Sie Ihre Anwendung in einem anderen Terminal und bereiten Sie sie darauf vor, beim Start mit
-p:DiagnosticSuspend=trueanzuhalten.Für Android-Emulatoren:
dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=10.0.2.2 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=true -p:DiagnosticListenMode=connectFür Android-Geräte:
dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=true -p:DiagnosticListenMode=connectFür iOS (Geräte und Simulatoren):
dotnet build -t:Run -c Release -f net10.0-ios -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=true -p:DiagnosticListenMode=listenIhre Anwendung wird auf dem Begrüßungsbildschirm angehalten und wartet darauf, dass
dotnet-traceeine Verbindung herstellt. Nach der Verbindung wird die Anwendung gestartet unddotnet-tracebeginnt mit der Aufzeichnung.Ermöglichen Sie es Ihrer Anwendung, den Anfangsbildschirm vollständig zu starten und zu erreichen.
Drücken Sie
<Enter>imdotnet-trace-Terminal, um die Aufzeichnung zu beenden.
Die Ablaufverfolgungsdatei wird im aktuellen Verzeichnis gespeichert. Verwenden Sie die -o Option, um ein anderes Ausgabeverzeichnis anzugeben.
Profiling-Laufzeitoperationen
Um bestimmte Vorgänge während der Laufzeit zu profilieren (z. B. Schaltflächentippen, Navigation oder Scrollen), verwenden -p:DiagnosticSuspend=false und verbinden Sie den Profiler, nachdem die Anwendung gestartet wurde.
Erstellen und bereitstellen Ihrer Anwendung mit
-p:DiagnosticSuspend=false:dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=false -p:DiagnosticListenMode=connectNavigieren Sie zum Bereich Ihrer Anwendung, den Sie profilieren möchten.
Beginnen Sie
dotnet-tracemit der--dsrouterOption:dotnet-trace collect --dsrouter android --format speedscopeFühren Sie den Vorgang aus, den Sie profilieren möchten.
Drücken Sie
<Enter>, um die Ablaufverfolgung zu beenden.
Dieser Ansatz erzeugt eine fokussiertere Ablaufverfolgungsdatei, die nur den spezifischen Vorgang enthält, den Sie untersuchen.
Verstehen der Ablaufverfolgungsausgabe
Beim Erfassen einer Ablaufverfolgung mit dotnet-trace wird die Ausgabe ungefähr folgendermaßen angezeigt:
Process : $HOME/.dotnet/tools/dotnet-dsrouter
Output File : /tmp/hellomaui-app-trace
[00:00:00:35] Recording trace 1.7997 (MB)
Press <Enter> or <Ctrl+C> to exit...
Nach dem Drücken <Enter>wird die Ablaufverfolgung abgeschlossen:
Stopping the trace. This may take up to minutes depending on the application being traced.
Trace completed.
Writing: hellomaui-app-trace.speedscope.json
Anzeigen von Ablaufverfolgungsdateien
Das --format Argument steuert das Ausgabeformat:
-
nettrace(Standard): Kann in PerfView oder Visual Studio unter Windows angezeigt werden -
speedscope: JSON-Format, das auf jeder Plattform angezeigt werden kann unter https://speedscope.app/
Für plattformübergreifende Analysen verwenden Sie --format speedscope.
dotnet-trace collect --dsrouter android --format speedscope
Profilerstellung unter Windows
Während das plattformübergreifende dotnet-trace Tool unter Windows funktioniert, bietet die Plattform zusätzliche native Profilerstellungsoptionen, die möglicherweise bequemer sind.
Verwenden von Visual Studio Performance Profiler
Der Visual Studio Performance Profiler bietet integrierte Profilerstellung für .NET-Anwendungen. Schauen Sie sich die Tour zur Visual Studio-Profilierung für umfassende Anleitungen an.
Verwenden von PerfView
PerfView ist ein leistungsstarkes, kostenloses Leistungsanalysetool für Windows, das .NET MAUI-Anwendungen mit minimalem Setup profiliert.
Um mit PerfView zu profilieren:
Erstellen Sie Ihre Anwendung für
Releasemit aktiviertem ReadyToRun:dotnet publish -f net10.0-windows10.0.19041.0 -c Release -p:PublishReadyToRun=trueStarten Sie PerfView, und wählen Sie .
Collect>CollectFiltern Sie im Feld "Befehl" nach der ausführbaren Datei Ihrer App (z. B.
hellomaui.exe).Klicken Sie auf "Sammlung starten", und starten Sie die App dann manuell.
Klicken Sie auf "Sammlung beenden ", nachdem die App den Vorgang abgeschlossen hat, den Sie profilieren möchten.
Öffnen Sie CPU-Stapel, um Zeitinformationen anzuzeigen, oder verwenden Sie die Registerkarte Flammendiagramm für eine grafische Ansicht.
Sie können die PerfView-Daten auch im SpeedScope-Format (File>Save View As) speichern, um sie https://speedscope.app/ für plattformübergreifende Analysen anzuzeigen.
Messen der Windows-Startzeit mit PerfView
Um genaue Startzeiten unter Windows zu messen, können Sie PerfView verwenden, um Event Tracing für Windows (ETW)-Ereignisse zu erfassen.
Öffnen
Collect>Collectund erweitern Sie in PerfView erweiterte Optionen.Konfigurieren Sie Folgendes:
- Kernelbasis aktivieren
- Zu
Microsoft-Windows-XAML:0x44:Informationalhinzufügen
Klicken Sie auf „Sammlung starten“, öffnen und schließen Sie Ihre App 3-5 Mal.
Klicken Sie auf "Sammlung beenden".
Öffnen Sie den Ereignisbericht und berechnen Sie die Startzeit, indem Sie Folgendes finden:
- Das
Windows Kernel/Process/StartEreignis für Ihre App (beachten Sie denTime MSecWert) - Das erste
Microsoft-Windows-XAML/Frame/StopEreignis für dieselbe Prozess-ID - Subtrahieren Sie die Startzeit von der Stoppzeit, um die Startdauer zu berechnen.
- Das
Führen Sie die App mehrmals aus und mitteln Sie die Ergebnisse, um genauere Messungen zu erhalten.
Verwenden von dotnet-trace unter Windows
Für entpackte Windows-Anwendungen können Sie folgendes direkt verwenden dotnet-trace :
dotnet publish -f net10.0-windows10.0.19041.0 -c Release -p:PublishReadyToRun=true -p:WindowsPackageType=None
dotnet trace collect --format speedscope -- bin\Release\net10.0-windows10.0.19041.0\win10-x64\publish\YourApp.exe
Profilerstellung auf iOS und Mac Catalyst mit Instrumenten
Für iOS- und Mac Catalyst-Apps bietet das Apple Instruments-Tool native Profilerstellung mit detaillierten Einblicken in die App-Startzeit und App-Leistung.
Verwenden von Instrumenten für die Profilerstellung für den App-Start
Erstellen Sie Ihre App für
Release, wobei die Symbole beibehalten werden:dotnet build -c Release -f net10.0-ios -p:NoSymbolStrip=trueDie
NoSymbolStrip=trueEigenschaft behält systemeigene Symbole in der ausführbaren Datei bei, wodurch Stack-Traces in Instruments deutlich hilfreicher werden.Installieren Sie die App auf Ihrem Gerät:
dotnet build -t:Run -c Release -f net10.0-ios -p:NoSymbolStrip=trueStarten Sie Instruments (in Xcode oder durch Ausführen von
open -a Instrumentsim Terminal).Wählen Sie ihr iOS-Gerät oben aus.
Wählen Sie Ihre App aus der Liste der installierten Anwendungen aus.
Wählen Sie die App-Startinstrumentvorlage aus.
Klicken Sie auf "Auswählen", und klicken Sie dann auf die Schaltfläche " Aufzeichnen ", um die Profilerstellung zu starten.
Die App wird automatisch gestartet. Beenden Sie die Aufzeichnung, sobald die App vollständig gestartet wurde.
Wählen Sie in den Ergebnissen die Zeile "App-Lebenszyklus " aus, um die Lebenszykluszeitachse anzuzeigen. In der letzten Zeile der unteren Tabelle zeigt
Currently running in the foreground...den Zeitpunkt an, zu dem die App vollständig gestartet wurde (z. B.).
Weitere Informationen zur Verwendung von Instruments finden Sie in der Apple-Dokumentation zur Reduzierung der Startzeit Ihrer App.
Speicherverwendungsprofilierung
Die Speicherprofilerstellung hilft Ihnen, Speicherverluste zu identifizieren und Speicherzuordnungsmuster in Ihrer Anwendung zu verstehen. Verwenden Sie dotnet-gcdump, um Momentaufnahmen des verwalteten Speichers zu erstellen.
Sammeln von Speicherabbildern
Verwenden Sie zum Sammeln eines Speicherabbilds denselben --dsrouter Workflow wie dotnet-trace:
dotnet-gcdump collect --dsrouter android
Verwenden Sie --dsrouter android-emu, --dsrouter iosoder --dsrouter ios-sim für andere Ziele.
Im Gegensatz zur CPU-Ablaufverfolgung erfordern Speicherabbilder nicht das Anhalten des Anwendungsstarts. Erstellen Sie Ihre Anwendung mit -p:DiagnosticSuspend=false:
dotnet build -t:Run -c Release -f net10.0-android -p:DiagnosticAddress=127.0.0.1 -p:DiagnosticPort=9000 -p:DiagnosticSuspend=false -p:DiagnosticListenMode=connect
Sobald dotnet-gcdump eine Verbindung hergestellt wird, wird eine *.gcdump Datei im aktuellen Verzeichnis erstellt. Sie können diese Datei in Visual Studio unter Windows oder PerfView öffnen.
Analysieren von Speicherabbilder
Wenn Sie eine *.gcdump Datei in Visual Studio öffnen, können Sie:
- Anzeigen aller verwalteten Objekte im Arbeitsspeicher
- Die Gesamtanzahl und -größe jedes Typs anzeigen
- Überprüfen des Referenzbaums, um zu verstehen, was Objekte am Leben hält
- Vergleichen Sie mehrere Momentaufnahmen, um wachsende Allokationen zu identifizieren.
Mit dem Diagnosetool für die Speicherauslastung von Visual Studio (Debug>Windows>Diagnostic Tools) können Sie auch Momentaufnahmen beim Debuggen erstellen, sie sollten jedoch das erneute Laden von XAML deaktivieren, um genaue Ergebnisse zu erzielen.
Tipp
Erwägen Sie die Erstellung von Speichermomentaufnahmen von Release Builds, da Codepfade erheblich unterschiedlich sein können, wenn die XAML-Kompilierung, die AOT-Kompilierung und das Trimming aktiviert sind.
Diagnostizieren von Speicherlecks
Speicherverluste in .NET MAUI-Anwendungen manifestieren sich als stetig steigende Speicherauslastung, insbesondere während wiederholter Navigation oder Interaktionen. Auf mobilen Plattformen kann dies dazu führen, dass das Betriebssystem Ihre Anwendung aufgrund eines übermäßigen Arbeitsspeicherverbrauchs beendet.
Symptome von Speicherlecks
Ein typisches Symptom für einen Speicherverlust kann sein:
- Navigieren von der Hauptseite zu einer Detailseite
- Zurück navigieren
- Zur Detailseite erneut navigieren
- Der Speicher wächst mit jedem Zyklus konsistent.
Ermitteln, ob ein Leck vorhanden ist
Um festzustellen, ob eine Seite tatsächlich ausläuft, verwenden Sie Finalizer mit Protokollierung und erzwungener Garbage Collection (Speicherbereinigung) während des Debugging-Prozesses.
Fügen Sie einen Finalizer mit Protokollierung zur Seitenklasse hinzu:
~MyDetailsPage() => System.Diagnostics.Debug.WriteLine("~MyDetailsPage() finalized");Erzwingen der Garbage Collection an strategischen Stellen (nur für das Debuggen):
public MyDetailsPage() { GC.Collect(); // For debugging purposes only GC.WaitForPendingFinalizers(); InitializeComponent(); }Testen Sie einen
ReleaseBuild, und beobachten Sie die Konsolenausgabe mithilfe von adb logcat (Android) oder Geräteprotokollen (iOS).
Wenn der Finalizer beim Verlassen der Seite ausgeführt wird, wird die Seite korrekt erfasst. Wenn der Finalizer niemals ausgeführt wird, tritt ein Speicherleck auf – etwas hält unbegrenzt einen Verweis darauf.
Warnung
Entfernen Sie GC.Collect() Aufrufe nach dem Debuggen. Sie dienen nur der Diagnose von Problemen und sollten niemals im Produktionscode enthalten sein.
Einschränken der Ursache
Nachdem Sie ein Leck identifiziert haben, schränken Sie die Ursache ein:
- Kommentieren Sie alle XAML-Inhalte aus. Tritt das Leck noch auf?
- Kommentieren Sie den gesamten C#-Code im CodeBehind aus. Tritt das Leck noch auf?
- Testen Sie auf mehreren Plattformen. Geschieht es nur auf einer Plattform?
Im Allgemeinen sollte ein leerer ContentPage Wert nicht geleert werden. Durch das systematische Entfernen von Code können Sie ermitteln, welches Steuerelement oder Codemuster das Problem verursacht.
Allgemeine Leckmuster
C#-Ereignisse
C#-Ereignisse können Zirkelverweise erstellen, die die Garbage Collection verhindern. Betrachten Sie ein Szenario, in dem ein untergeordnetes Objekt das Ereignis eines übergeordneten Elements abonniert, aber das übergeordnete Objekt auch einen Verweis auf das untergeordnete Element enthält. Beide Objekte können für immer leben.
Wenn die Ereignisquelle den Abonnent (z. B. ein Style In Application.Resources) überlebt, kann dies dazu führen, dass ganze Seiten verloren gehen.
Lösung: Verwenden Sie WeakEventManager für Ereignisse in .NET MAUI-Steuerelementen oder melden Sie sich von Ereignissen ab, wenn das Objekt nicht mehr benötigt wird.
iOS- und Mac Catalyst-Zirkelbezüge
Bei iOS und Mac Catalyst können Zirkelverweise zwischen C#-Objekten und nativen Objekten zu Lecks führen, da C#-Objekte, die Unterklassen NSObject sowohl in der Garbage-Collection .NET-Welt als auch in der referenzgezählten Objective-C-Welt vorhanden sind.
Beispiel für ein problematisches Muster:
class MyView : UIView
{
public MyView()
{
var picker = new UIDatePicker();
AddSubview(picker); // MyView -> UIDatePicker
picker.ValueChanged += OnValueChanged; // UIDatePicker -> MyView via event handler
}
void OnValueChanged(object? sender, EventArgs e) { }
}
Lösungen:
Erstellen von Ereignishandlern
static:static void OnValueChanged(object? sender, EventArgs e) { }Verwenden Sie ein Proxyobjekt, das nicht von
NSObjecterbt.class MyView : UIView { readonly Proxy _proxy = new(); public MyView() { var picker = new UIDatePicker(); AddSubview(picker); picker.ValueChanged += _proxy.OnValueChanged; } class Proxy { public void OnValueChanged(object? sender, EventArgs e) { } } }
Hinweis
Diese Zirkelreferenzprobleme sind spezifisch für iOS und Mac Catalyst. Sie treten normalerweise nicht auf Android oder Windows auf.
Bewährte Methoden zum Vermeiden von Lecks
Testbuilds
Release: Das Speicherverhalten kann sich aufgrund von Optimierungen, Kürzen und AOT-Kompilierung erheblich vonDebugBuilds unterscheiden.Verwenden Sie Finalizer bei der Untersuchung: Fügen Sie Finalizer mit Protokollierung zu wichtigen Objekten hinzu, um schnell zu ermitteln, ob sie gesammelt werden.
Von Ereignissen abmelden: Melden Sie sich immer von Ereignissen ab, wenn Objekte verworfen oder nicht mehr benötigt werden.
Seien Sie vorsichtig mit Ereignissen für langlebige Objekte: Vermeiden Sie es, dass langlebige Objekte (z. B. solche in
Application.Resources) Verweise auf kurzlebige Objekte (z. B. Seiten oder Ansichten) halten.Regelmäßiges Profiling: Machen Sie Speicherprofilierung zu einem Teil Ihres regelmäßigen Testprozesses, insbesondere nachdem Sie neue Features hinzugefügt oder erhebliche Änderungen vorgenommen haben.
Ausführlichere Informationen zu Speicherleckmustern und -techniken finden Sie im .NET MAUI Memory Leaks-Wiki.
Alternative Profilerstellungsansätze
Android ActivityManager-Startprotokolle
Android protokolliert automatisch Startzeitinformationen über den ActivityManager. Sie können diese Protokolle mithilfe von adb logcat:
adb logcat | grep "ActivityManager"
Wenn Ihre App gestartet wird, werden Nachrichten wie folgt angezeigt:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
Dies zeigt die Zeit an, die für die Anzeige Ihrer Aktivität benötigt wurde. Dies ist eine schnelle Möglichkeit, die Startzeit ohne zusätzliche Tools oder Codeänderungen zu messen.
Weitere Informationen zur Startzeit und Optimierungstechniken für Android-Apps finden Sie in der Android-Dokumentation zur Startzeit der App.
Loggingbasierte Startmessung
Um die Startzeit auf allen Plattformen zu messen, können Sie Nachrichten an bestimmten Stellen in Ihrer Anwendung protokollieren und die Zeit zwischen ihnen messen:
Fügen Sie beim Laden der Hauptseite eine Protokollmeldung hinzu:
Loaded += (sender, e) => Dispatcher.Dispatch(() => Console.WriteLine("loaded"));Verwenden Sie ein Werkzeug wie das measure-startup Beispiel, um Ihre App zu starten und die Zeit zu messen, bis die Lognachricht angezeigt wird.
Unter Android können Sie die Ausgabe
adb logcatfiltern, um bestimmte Nachrichten zu überwachen.adb logcat | grep "loaded"
Dieser Ansatz funktioniert auf allen Plattformen und ist nützlich für fortlaufende Integrationsszenarien oder Schnellprüfungen.
Zusätzliche Ressourcen
- .NET MAUI Profiling Wiki - Umfassendes Wiki mit erweiterten Szenarien und Problembehandlung
- Android Tracing-Handbuch – Detaillierte Android-spezifische Profilierungsanweisungen
- iOS/macOS Profiling Wiki – Plattformspezifische Anleitungen für Apple-Plattformen
-
Dokumentation zu .NET-Diagnosetools – Offizielle Dokumentation für
dotnet-trace,dotnet-dsrouterunddotnet-gcdump - PerfView User's Guide – Ausführliche Anleitung zur Verwendung von PerfView für Windows-Profilerstellung