2011-06-24 3 views
9

J'essaie de comprendre comment fonctionne la fragmentation de tas. Que me dit la sortie suivante?fragmentation de tas géré

Ce tas est-il trop fragmenté?

J'ai 243010 "objets libres" avec un total de 53304764 octets. Est-ce que ces espaces "objets libres" dans le tas qui contenaient autrefois l'objet mais qui sont maintenant recueillis?

Comment puis-je forcer le nettoyage d'un tas fragmenté?

!dumpheap -type Free -stat 
total 243233 objects 
Statistics: 
     MT Count TotalSize Class Name 
0017d8b0 243010  53304764  Free 

Répondre

6

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.

+0

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

+0

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. –

0

Vous disposez de 50 Mo de RAM en tant qu'espace libre. Ce n'est pas bien.

Lorsque .NET allouant des blocs de 16 Mo à partir du processus, nous avons effectivement un problème de fragmentation. Il existe de nombreuses raisons de fragmentation pour se produire dans .NET.

Regardez here et here. Dans votre cas, c'est peut-être un épinglage. Comme 53304764/243010 fait 219.35 octets par objet - beaucoup plus bas que les objets LOH.

+0

Ok, j'ai 50 Mo d'espace libre, mais que me dit * Count *? Je sais que je crée fréquemment beaucoup de petits objets (c'est-à-dire que je crée une grille de ~ 20000 contrôles WPF toutes les 10 secondes, mais les anciens ne sont plus référencés, pas de fuite de mémoire ici). Cela pourrait-il l'expliquer ou devrait-il y avoir des objets épinglés plus probables? – bitbonk

Questions connexes