Sehr hohe GC-Thread-Anzahl in einer ServerGC-App

8

TL; DR: Eine Server-GC-fähige Anwendung zeigt dutzende von speziellen GC-Threads und hängt Überstunden. Was kann das erklären?

Ich stehe heutzutage an einem seltsamen Multi-Threading / Contention-Problem, das bei einem .NET-Dienst auftritt. Die Symptome sind folgende:

  • Das Programm hängt für eine lange Zeit (Sekunden bis Minuten)
  • Die Anzahl der Threads ist ungewöhnlich hoch
  • Es gibt einen Höhepunkt der Konkurrenz, nur wenn das Programm aufhört zu antworten (siehe folgendes Diagramm)
  • Dasselbe Programm wird auf verschiedenen Servern bereitgestellt, und einige Instanzen haben überhaupt kein Problem (gleiche Hardware / OS / CLR)

Ich habe sofort ein Problem in unserem Code vermutet, das dazu geführt hätte, dass der verwaltete Threadpool im Laufe der Zeit eine große Anzahl von Threads gestartet hat, die alle versuchen, eine oder mehrere gemeinsame Ressourcen zu teilen. Es schien, dass wir eine sehr kleine und sehr kontrollierte Verwendung des ThreadPools hatten.

Ich habe es geschafft, eine Dump-Datei eines noch nicht hängenden Dienstes zu erhalten, der bereits eine sehr hohe Anzahl von Threads hatte (mehr als 100, wenn es in einem normalen Zustand etwa 20 sein sollte)

Mit windbg + sos haben wir festgestellt, dass die ThreadPool-Größe in Ordnung war:

%Vor%

Nur 8 Worker-Threads ... Dann habe ich alle verwalteten Thread-Stacks aufgelistet und viele gefunden, die ich nicht erkennen konnte. Siehe unten für ein Beispiel:

%Vor%

Mit !threads -special command fand ich schließlich, dass diese Threads spezielle GC-Threads waren:

%Vor%

Mehr als 60 "GC" -Threads ... Also überprüfte ich die Einstellungen meiner verschiedenen Dienstinstanzen und fand heraus, dass die problematischen mit GC Server konfiguriert wurden, während die anderen nicht.

Weitere Informationen:

  • Wir verwenden .NET 4.5
  • Wir verwenden Windows 2012 Server auf allen Computern
  • Wir laufen auf Bi-Octo-Core-Servern (2 CPUs, 16 physische Kerne, 32 logische Kerne)

Was ich jetzt versuche zu tun:

  • Ich versuche, andere Dumps zu bekommen (wenn das Programm noch mehr Threads hat, wenn das Programm hängt, usw.)
  • Ich werde versuchen, die Einstellung GC Server für die problematischen Instanzen zu deaktivieren, aber das Problem kann einige Zeit dauern.

Hier sind meine Fragen :

  • Ist es normal für ein GC-Server-konfiguriertes .NET-Programm, so viele GC-Threads zu haben? Ich dachte, Server GC hätte nur einen GC-Thread pro Prozessor.
  • Kann dies mit dem Problem zusammenhängen, das ich bei diesen Diensten sehe, d. h. hunderte von Threads im Laufe der Zeit, mit großem Prozessstopp aufgrund von Konflikten?
Romain Verdier 12.09.2013, 10:08
quelle

2 Antworten

1

Bei Server-GC gibt es einen Thread pro logischem Kern (das heißt Affinitätssatz für diesen Kern). In deinem Fall sollte es mindestens 32 Threads geben. Wenn Sie den Hintergrund-GC aktiviert haben, könnten weitere Worker-Threads das Diagramm für jeden Heap verarbeiten (reference ).

Beachten Sie auch, dass diese GC-Threads bei THREAD_PRIORITY_HIGHEST ausgeführt werden, wodurch alle Threads, die vom GC noch nicht pausiert wurden, problemlos ausgehungert werden können ( Referenz ).

Nun, was Ihre anderen Threads anbelangt, wird 500+ in einem Prozess trotz des Garbage Collectors viele Konflikte erzeugen. Für Ihre Untersuchungen ist es wichtig, herauszufinden, was diese Threads sind.


Dinge, die Sie sich ansehen sollten

  • Sehen Sie, ob Hintergrund-GC aktiviert ist, und falls ja, versuchen Sie, ohne es zu laufen (dieser Modus wird in 4.5 Server-GC unterstützt).
  • Versuchen Sie, die maximale Anzahl von Threads in Ihren Thread-Pools zu reduzieren (32767 ist ein ungesundes Maximum).

Sie können auch procdump.exe verwenden, um Minidumps zu erfassen, wenn die Leistung abnimmt.

    
josh poley 17.09.2013 15:55
quelle
0

Ich hatte ähnliche Probleme auf einem NUMA-Server. Dinge, die mir geholfen haben:

  • Begrenzen Sie den Threadpool
  • Begrenzen Sie die Prozessor-Affinitätsmaske für den verwalteten Prozess, der hängen bleibt. Es sieht merkwürdig aus, aber wenn die Anzahl der Prozessoren für einen Prozess reduziert wird, arbeitet es manchmal schneller bei hoher Parallellast. Ich vermute Spin Locks (busy Waits).
Aleksandr 22.10.2013 06:47
quelle