Suspension du GC
Avant la plupart des collectes, le runtime doit suspendre tous les threads managés. Le temps que cela prend est le temps de suspension.
Avant la plupart des collectes, le runtime doit suspendre tous les threads managés. Le temps que cela prend est le temps de suspension.
Les threads managés sont arrêtés à des points sûrs de leur code. Les threads en code natif sont marqués pour ne pas pouvoir revenir en code managé pendant la collecte. Un thread qui n'atteint pas vite un point sûr (une longue boucle serrée, une longue opération) retarde toute la collecte pendant que les autres attendent.
Dans les traces .NET, le temps de suspension est rapporté séparément du temps de collecte. GC Doctor le trace pour qu'on puisse attribuer une longue pause au collecteur ou à l'attente qui la précède. Les longues suspensions viennent souvent de boucles chaudes, d'une famine du pool de threads ou d'une machine surchargée.
GC en arrière-plan
Collecte concurrente de la génération 2, qui laisse les collectes gen 0 et gen 1 s'exécuter entre-temps.
Une collecte gen 2 bloquante arrête tous les threads managés pendant longtemps. Avec le GC en arrière-plan (activé par défaut, paramètre System.GC.Concurrent), un thread dédié marque gen 2 en concurrence avec l'application. Si gen 0 se remplit entre-temps, une collecte de premier plan des générations éphémères suspend brièvement les threads, s'exécute, puis laisse la collecte en arrière-plan continuer.
Seule une collecte gen 2 qui ne peut pas être en arrière-plan, par exemple quand elle est provoquée comme bloquante ou quand la mémoire est très basse, est une longue pause. Le GC en arrière-plan réduit les temps de pause au prix d'un peu de CPU et de mémoire. GC Doctor étiquette les collectes .NET en arrière-plan ou bloquantes, ce qui explique pourquoi une collecte gen 2 a ou non causé une longue pause.
Documentation officielle : Background garbage collection (Microsoft Learn)
Générations (gen 0, 1, 2)
Le tas managé de .NET est divisé par âge : gen 0 pour les nouveaux objets, gen 1 comme tampon, gen 2 pour les objets de longue durée.
Une collecte de la génération N collecte aussi toutes les générations plus jeunes : une collecte gen 1 inclut gen 0, et une collecte gen 2, dite complète ou bloquante, couvre tout le tas y compris le tas des gros objets. Les survivants de gen 0 sont promus en gen 1, ceux de gen 1 en gen 2. Gen 0 et gen 1 sont les générations éphémères ; elles sont petites et rapides à collecter.
Une application saine montre beaucoup de collectes gen 0, moins de gen 1 et peu de gen 2. Une part élevée de collectes gen 2, ou des collectes gen 1 qui promeuvent beaucoup, signifie que des objets survivent plus longtemps qu'ils ne devraient : caches, rafales d'allocation, objets maintenus en vie par des finaliseurs. Les événements GC d'un .nettrace donnent la génération et la raison de chaque collecte ; GC Doctor les trace par génération.
Documentation officielle : Fundamentals of garbage collection (Microsoft Learn)
Suspension du GC