Mes deux cents sur la méthode GC.Collect en C #

La méthode GC.Collect () est depuis longtemps populaire parmi les développeurs .Net. Cependant, peu d'entre nous savent comment cela fonctionne réellement ou, si un appel est nécessaire.

Le CLR (Common Language Runtime) adopte le garbage collection comme mécanisme pour nettoyer les ressources consommées par votre application. Notez que lorsque vous créez des objets dans .Net, ils sont stockés dans le tas géré, et lorsque vous avez fini de les utiliser, vous n'avez pas à vous soucier de leur nettoyage - le runtime le ferait pour vous.

Le CLR organise le tas géré en générations. Les trois générations dans lesquelles le tas géré est organisé sont: Génération 0, Génération 1 et Génération 2. Le GC est capable de récupérer la mémoire occupée par les objets gérés. Cependant, vous devez suivre certaines directives pour accélérer la récupération de place afin d'améliorer les performances de votre application.

Dois-je utiliser la méthode GC.Collect ()?

Tout d'abord, avez-vous besoin d'appeler GC.Collect dans le code de votre application? La réponse dans la plupart des cas est non. Laissez-moi maintenant vous dire ce que fait cette méthode et pourquoi vous devriez vous abstenir d'appeler cette méthode dans la plupart des cas.

Lorsque vous effectuez un appel à la méthode GC.Collect (), le runtime effectue un parcours de pile pour déterminer les objets qui sont accessibles et ceux qui ne le sont pas. Il gèle également le thread principal (ainsi que tous les threads enfants qu'il a créés) de l'application. En d'autres termes, lorsque la méthode GC.Collect () est appelée, le runtime effectue un garbage collection bloquant de toutes les générations.

Je préférerais toujours ne pas utiliser GC.Collect () sauf s'il y a une raison spécifique de l'utiliser. Un GC se compose généralement des phases de marquage et de balayage suivies d'une phase de compactage. Le temps passé par le runtime à exécuter un GC peut devenir un goulot d'étranglement, donc, ne l'utilisez que très rarement et si vous en avez vraiment besoin. Rico Mariani déclare: "Envisagez d'appeler GC.Collect () si un événement non récurrent vient de se produire et que cet événement est très susceptible d'avoir causé la mort de nombreux objets anciens."

Utilisation de la méthode GC.Collect ()

Voici comment vous pouvez appeler la méthode GC.Collect () dans votre code.

GC.Collect();

Notez que vous pouvez également collecter des objets appartenant à une génération spécifique.

GC.Collect() - utilisé pour collecter des objets présents dans les générations 0, 1, 2

GC.Collect(0) - utilisé pour collecter les objets présents dans la génération 0

GC.Collect(1) - utilisé pour collecter des objets présents dans les générations 0 et

Vous pouvez également déterminer la quantité de mémoire libérée en appelant la méthode GC.Collect (). Pour ce faire, vous pouvez tirer parti de la méthode System.GC.GetTotalMemory () comme indiqué dans l'extrait de code ci-dessous.

//Write code to create some large objects here

Console.WriteLine("Total available memory before collection: {0:N0}", System.GC.GetTotalMemory(false));

System.GC.Collect();

Console.WriteLine("Total available memory collection: {0:N0}", System.GC.GetTotalMemory(true));

La méthode GC.GetGeneration () peut être utilisée pour connaître la génération à laquelle appartient un objet. Reportez-vous à la liste des codes ci-dessous.

static void Main(string[] args)

       {

           List obj = new List() { "Joydip", "Steve" };

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           Console.Read();

       }

Lorsque vous exécutez le programme ci-dessus, voici ce qui est imprimé dans la fenêtre de la console.

0

1

2

Comme vous pouvez le voir, chaque appel à la méthode GC.Collect () promeut l'objet "obj" vers la prochaine génération supérieure. Ceci est dû au fait que l'objet "obj" survit à la récupération de place dans chacun des deux cas, c'est-à-dire qu'il n'est récupéré dans aucun des deux appels effectués à la méthode GC.Collect ().

Vous pouvez forcer le garbage collection sur les trois générations ou sur une génération spécifique à l'aide de la méthode GC.Collect (). La méthode GC.Collect () est surchargée - vous pouvez l'appeler sans aucun paramètre ou même en passant le numéro de génération que vous souhaitez que le garbage collector collecte.

Notez que les objets qui ont des finaliseurs (et si un appel à la méthode SuppressFinalize n'a pas été effectué) ne seront pas collectés lors d'un appel à la méthode GC.Collect (). Au contraire, ces objets seraient placés dans la file d'attente de finalisation. Si vous souhaitez également collecter ces objets, vous devez appeler la méthode GC.WaitForPendingFinalizers () afin que ces objets soient nettoyés lors du prochain cycle GC. En substance, la récupération de la mémoire occupée par les objets sur lesquels des finaliseurs sont implémentés nécessite deux passes, car ces objets sont placés dans la file d'attente de finalisation plutôt que d'être récupérés lors de la première passe lorsque le garbage collector s'exécute.