11 Stimmen

Bestimmen, welcher Garbage Collector gerade läuft

Ich führe eine große .NET 4.0 x86-Anwendung auf Windows Server 2003 x64 (2x Xeon 4-Kern-Prozessoren) aus und stoße auf Probleme, bei denen meine Anwendung etwa 2-3 Mal am Tag für 30 Sekunden einfriert und dann wieder normal funktioniert. Die Anwendung wird nur einmal pro Woche neu gestartet und verbraucht 400-800 MB Speicher, daher gehe ich davon aus, dass diese Einfrierungen durch die Garbage Collection verursacht werden. Ich sehe die Einfrierungen nur in den Logs, nicht live, sonst würde ich den Task-Manager überprüfen, um dies zu bestätigen.

Ich versuche herauszufinden, welche .NET 4 GC läuft, und wie ich entweder den GC auf die neue parallele Hintergrund-GC umschalten kann, falls dies nicht der Fall ist, oder wie ich bestätigen kann, dass es sich tatsächlich um GCs handelt (Procmon zeigt keine .NET-Instrumente auf Win2k3-Server).

33voto

Dave Black Punkte 6469

Ich habe diese Antwort auf meinem Blog erneut veröffentlicht: http://dave-black.blogspot.com/2012/04/how-to-determine-which-garbage.html

Sie können feststellen, welche Version des GC Sie verwenden, auf zwei Arten:

  1. Aufruf der System.Runtime.GCSettings.IsServerGC Eigenschaft
  2. Anhängen an den Prozess mit WinDbg und Überprüfung, wie viele GC-Threads Sie haben, indem Sie den Befehl "!sos.threads" (ohne Anführungszeichen und gemäß den unten stehenden Kriterien) verwenden...

Sie haben nicht angegeben, um welche Art von App es sich handelt. Wenn Sie eine Konsolen-App, eine WinForm-App oder einen Windows-Dienst ausführen, erhalten Sie den Workstation-GC. Nur weil Sie auf einem Serverbetriebssystem ausgeführt werden, heißt das nicht, dass Sie die Serverversion des GC erhalten. Wenn Ihre App nicht auf einer Multi-Prozessor-Maschine gehostet ist, erhalten Sie standardmäßig den Workstation-GC - Concurrent. Wenn Ihre App auf einer Multi-Prozessor-Maschine gehostet ist, erhalten Sie standardmäßig den Server-GC.

Jede IIS- oder CLR-selbstgehostete App wird standardmäßig im Server-GC-Modus ausgeführt.

Folgendes gilt für jeden .NET-Verwalteten Prozess:

Workstation-GC

  • Einzeln-Proc-Maschine
  • Immer Threads aussetzen
  • 1 Ephemeral GC-Heap (SOH), 1 LOH GC-Heap
  • Läuft auf dem Thread, der GC ausgelöst hat
  • Threadpriorität entspricht der des Threads, der GC ausgelöst hat

Workstation-GC - Concurrent

  • Läuft nur nebenläufig in Gen2/LOH (volle Sammlung)
  • Gegensätzlich zum Server-Modus
  • Etwas größere Arbeitsmenge
  • GC-Thread läuft ab, wenn er eine Weile nicht verwendet wird
  • 1 Ephemeral GC-Heap (SOH), 1 LOH GC-Heap
  • Gewidmeter GC-Thread
  • Threadpriorität ist Normal

Server-GC

  • Größere Segmentgrößen
  • Schneller als Workstation-GC
  • Immer Threads aussetzen
  • 1 Ephemeral GC-Heap (SOH) für jeden logischen Prozessor (einschließlich Hyperthreading), 1 LOH GC-Heap für jeden logischen Prozessor (einschließlich Hyperthreading)
  • Gewidmete GC-Threads
  • Threadpriorität ist THREAD_PRIORITY_HIGHEST

Es gibt nur 1 Finalisierer-Thread pro verwaltetem Prozess, unabhängig vom GC-Modus. Selbst während eines nebenläufigen GC werden verwaltete Threads zweimal ausgesetzt (blockiert), um einige Phasen des GC durchzuführen.

Ein selten bekannter Fakt ist, dass selbst wenn Sie den Servermodus des GC einstellen, es sein kann, dass Sie nicht im Server-GC ausgeführt werden; der GC bestimmt letztendlich, welcher Modus für Ihre App optimal ist und WIRD Ihre Einstellungen außer Kraft setzen, wenn er feststellt, dass Ihre ServerGC-Einstellung sich negativ auf Ihre Anwendung auswirken wird. Auch jede gehostete CLR-App auf einer uniprozessorischen Maschine wird von manuellen GC-Einstellungen außer Kraft gesetzt - in diesem Fall verwendet die CLR immer den Workstation-GC-Modus.

In CLR 4.0 ändert sich nur wenig

  • Nebenläufiger GC wird jetzt Hintergrund-GC
  • Hintergrund-GC gilt nur für Workstation-GC
  • Alt (Nebenläufiger GC):
    • Während eines vollen GC sind Zuweisungen bis zum Ende der Größe des ephemeren Segments erlaubt
    • Ansonsten setzt alle anderen Threads aus
  • Neu (Hintergrund-GC):
    • Erlaubt gleichzeitig ephemere GCs mit Hintergrund-GCs, falls erforderlich
    • Die Leistung ist deutlich schneller
  • Der Server-GC blockiert immer Threads für die Sammlung jeder Generation

In CLR 4.5 ändert sich nur wenig... wieder

  • Hintergrund-Server-GC:
    • Der Server-GC blockiert nicht mehr. Stattdessen verwendet er dedizierte Hintergrund-GC-Threads, die parallel mit dem Benutzercode ausgeführt werden können - siehe MSDN: Hintergrund-Server-GC

Daher haben ab .NET 4.5 alle Anwendungen Hintergrund-GC verfügbar, unabhängig vom verwendeten GC.

.NET 4.7.1 GC-Verbesserungen

.NET Framework 4.7.1 bringt Änderungen in der Garbage Collection (GC) zur Verbesserung der Zuweisungsleistung, insbesondere für Large Object Heap (LOH)-Zuweisungen. Dies liegt an einem architektonischen Wechsel, um das Zuordnungsschloss des Heaps in 2 für Small Object Heap (SOH) und LOH zu trennen. Anwendungen, die viele LOH-Zuweisungen vornehmen, sollten eine Verringerung der Zuweisungssperre sehen und eine bessere Leistung erfahren. Diese Verbesserungen ermöglichen LOH-Zuweisungen, während der Hintergrund-GC (BGC) SOH bereinigt. Normalerweise wartet der LOH-Allokator die gesamte Dauer des BGC-Sweep-Vorgangs ab, bevor er Anforderungen zur Speicherzuweisung erfüllen kann. Dies kann die Leistung beeinträchtigen. Sie können dieses Problem in den GCStats von PerfView beobachten, wo es eine Tabelle "LOH-Zuweisungspause (durch Hintergrund-GC) > 200 msec Ereignisse" gibt. Der Pausengrund ist "Warten auf BGC, um Freilisten zu durchsuchen". Diese Funktion sollte dazu beitragen, dieses Problem zu mildern.

2voto

Hans Passant Punkte 894572

Du läufst auf der Serverversion von Windows, du erhältst standardmäßig die Serverversion des Garbage Collectors. Diese führt keine Hintergrundsammlungen durch, der Müll wird von mehreren Threads gesammelt, daher sind gelegentliche erkennbare Pausen nicht ungewöhnlich. Du kannst die Workstationversion mit einer app.exe.config-Datei erzwingen:

Siehe auch die Dokumentation für die GC.RegisterForFullGCNotification()-Methode, um mit den Auswirkungen der Pausen umzugehen.

.NET Version 4.5 wird Hintergrundsammlungen für den Server-GC unterstützen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X