Cela dépend de la façon dont votre tas est organisé. Vous devriez voir combien de mémoire dans Gen 0,1,2 est allouée et combien de mémoire libre vous avez par rapport à la mémoire totale utilisée. Si vous avez utilisé 500 Mo de tas gérés mais que 50 Mo sont libres, alors vous vous en sortez plutôt bien. Si vous effectuez des opérations gourmandes en mémoire telles que la création de nombreux contrôles WPF et leur libération, vous avez besoin de beaucoup plus de mémoire pour une courte durée mais .NET ne restitue pas la mémoire au système d'exploitation une fois que vous l'avez allouée. Le GC essaie de reconnaître les modèles d'allocation et a tendance à garder votre empreinte mémoire élevée, bien que votre taille de tas actuelle soit trop grande jusqu'à ce que votre machine soit à court de mémoire physique.
J'ai trouvé beaucoup plus facile d'utiliser psscor2 pour .NET 3.5 qui a quelques commandes cool comme ListNearObj où vous pouvez trouver quels objets sont autour de vos trous de mémoire (objets épinglés?). Avec les commandes de psscor2, vous avez de meilleures chances de découvrir ce qui se passe réellement dans vos tas. La plupart des commandes sont également disponibles dans SOS.dll dans .NET 4.
Pour répondre à votre question initiale: Oui, les objets libres sont des espaces sur le tas géré qui peuvent simplement être le bloc de mémoire libre après votre dernier objet alloué sur un segment GC. Ou si vous le faites! DumpHeap avec l'adresse de début d'un segment GC, vous voyez les objets alloués dans ce segment de tas géré avec vos objets libres qui sont des objets collectés par GC.
Ces trous de mémoire se produisent normalement dans Gen2. Les adresses d'objet avant et après l'objet libre vous indiquent quels objets potentiellement épinglés se trouvent autour de votre trou. À partir de là, vous devriez être en mesure de déterminer votre historique d'allocation et de l'optimiser si nécessaire. Vous pouvez trouver les adresses des GC avec monceaux
0:021> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x101da9cc
generation 1 starts at 0x10061000
generation 2 starts at 0x02aa1000
ephemeral segment allocation context: none
segment begin allocated size
02aa0000 02aa1000** 03836a30 0xd95a30(14244400)
10060000 10061000** 103b8ff4 0x357ff4(3506164)
Large object heap starts at 0x03aa1000
segment begin allocated size
03aa0000 03aa1000 03b096f8 0x686f8(427768)
Total Size: Size: 0x115611c (18178332) bytes.
------------------------------
GC Heap Size: Size: 0x115611c (18178332) bytes.
Vous voyez que vous avez des tas à 02aa1000 et 10061000. Avec! Dumpheap 02aa1000 03836a30 vous pouvez vider le segment GC Heap.
!DumpHeap 02aa1000 03836a30
Address MT Size
...
037b7b88 5b408350 56
037b7bc0 60876d60 32
037b7be0 5b40838c 20
037b7bf4 5b408350 56
037b7c2c 5b408728 20
037b7c40 5fe4506c 16
037b7c50 60876d60 32
037b7c70 5b408728 20
037b7c84 5fe4506c 16
037b7c94 00135de8 519112 Free
0383685c 5b408728 20
03836870 5fe4506c 16
03836880 608c55b4 96
....
Vous y trouvez vos blocs de mémoire libre qui était un objet qui était déjà GCed. Vous pouvez vider les objets environnants (la sortie est triée par adresse) pour savoir s'ils sont épinglés ou s'ils ont d'autres propriétés inhabituelles.
Une fragmentation de tas peut-elle se produire (et éventuellement provoquer une exception OutOfMemoryException) ** sans ** objets épinglés? Je comprends que le GC est celui qui nettoie un tas fragmenté. Sans objets épinglés, le GC ne pourrait-il toujours pas nettoyer le tas à temps pour une nouvelle demande de mémoire? Qu'est-ce qui, sauf les objets épinglés, pourrait causer un tas fragmenté qui ne peut pas être nettoyé (à temps) quand de nouvelles allocations doivent être faites? – bitbonk
Si le taux d'allocation est très élevé, vous pouvez manquer de mémoire. Le clr a en effet un Sleep (50) intégré pour étrangler vos demandes d'allocation si vous allouez une boucle serrée pour donner au GC une chance de nettoyer mais cela peut ne pas suffire. –