2013-08-13 3 views
2

Je ne suis pas sûr parce que je n'ai pas beaucoup d'expérience dans l'analyse des vidages de mémoire, mais je pense que nous pouvons avoir des problèmes avec la fragmentation de la mémoire.Fragmentation de la mémoire?

Lors des tests de charge, nous constatons que l'utilisation de la mémoire augmente au point où l'application redémarre. Il s'agit de l'application ASP.NET MVC 4 sur une machine 64 bits. Je n'étais pas impliqué dans l'écriture. On m'a juste demandé d'essayer d'analyser les vidages mémoire.

Donc, lors du dernier test de charge nous avons créé 3 dumps mémoire (en dessous de leur taille et la production totale de la taille GC Tas de eeheap -gc):

  1. 1.70GB, 292MB
  2. 2.03GB, 337MB
  3. 2.55GB, 347MB

Alors que vous voyez le tas géré ne croît pas autant que les fichiers de vidage. Quand je fais dumpheap -stat je vois plus l'espace est utilisé par des objets libres (ci-dessous pour chaque fichier de vidage)

  1. 147MB
  2. 145MB
  3. 213MB
 
Fragmented blocks larger than 0.5 MB: 
      Addr  Size  Followed by 
000000bcc668e0a8 0.7MB 000000bcc6738650 System.Object[] 
000000bcc6949f88 4.4MB 000000bcc6dab820 System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry 
000000bd4626c4b8 0.7MB 000000bd463165f8 System.Byte[] 
000000bd463fcc48 51.5MB 000000bd4977baf0 System.Threading.ThreadStart 
000000be463600c8 0.7MB 000000be464108f0 Free 
000000bec67e50e0 1.1MB 000000bec690b020 System.Collections.Generic.List`1[[OurType, ANotherOurType]] 
000000bec690b0b8 3.2MB 000000bec6c3b170 System.Byte[] 
000000bfc6605e00 1.0MB 000000bfc6710190 Free 
000000bfc6743c58 32.8MB 000000bfc8806fe8 System.Threading.ExecutionContext 
000000c046200580 1.0MB 000000c0462ff2a0 SomeOurType 
000000c0463a1270 3.6MB 000000c046732ac0 Microsoft.Win32.SafeHandles.SafeCapiKeyHandle 

D'après ce que je comprendre que ce n'est pas un problème lorsque les objets libres ne représentent qu'une petite fraction de la quantité totale de mémoire dans toutes les tailles de tas. On dirait que c'est un problème.

L'application utilise deux bibliothèques externes. Un pour créer des fichiers PDF et d'autres pour créer des fichiers de codes à barres. La bibliothèque de codes à barres lance AccessViolationException (environ 70 fois pour 2200 tentatives). Il jette avec cette stacktrace

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    at System.Drawing.SafeNativeMethods.Gdip.IntGdipDeleteGraphics(HandleRef graphics) 
    at System.Drawing.Graphics.Dispose(Boolean disposing) 
    at System.Drawing.Graphics.Dispose() 
    at Lesnikowski.Barcode.BaseBarcode.Render() 
    at Lesnikowski.Barcode.BaseBarcode.Save(Stream stream, ImageType imageType) 

I've read that memory fragmentation is often caused by pinning memory, but this is !gchandles output

 
Handles: 
    Strong Handles:  154 
    Pinned Handles:  23 
    Ref Count Handles: 2 
    Weak Long Handles: 1794 
    Weak Short Handles: 74 
    SizedRef Handles:  17 
    Dependent Handles: 1 

I don't know what else I can check. Do we have memory fragmentation problem? Can you point me in some direction?

Edit: I attach performance counters collected during load test. Weird because it's showing a lot of pinned objects but !gchandles didn't show them.

enter image description here

 
red line - user load 
green line - bytes in all heaps 
blue line - pinned objects 

Edit2: Added Fragmented blocks larger than 0.5 MB: output from !dumpheap -stat

+2

La fragmentation de la mémoire peut provoquer des MOO; Cependant, cela ressemble à un bogue BCL simple - cela ne devrait pas être une erreur de cette manière, fragmentée ou non. –

+0

Vous voulez dire ces AccessViolationExceptions? Cela peut être le bogue de BCL ou de notre bibliothèque BarCode. Mais je ne suis pas sûr que ce soit lié à la croissance de la mémoire. –

Répondre

2

You should use !address -summary pour avoir une idée de l'utilisation de la mémoire virtuelle dans ce processus. Même s'il semble y avoir une certaine fragmentation de tas, il y a très probablement un consommateur supplémentaire de mémoire lourd dans votre processus. Il peut s'agir du tas Win32, des piles de threads, des assemblages que vous chargez dynamiquement, etc.

Pour chaque type de fuite, vous devrez alors suivre une approche légèrement différente. Pour l'inspection de tas Win32, vous devez utiliser les variantes de la commande !heap - !heap -stat, !heap -s -h 0. Pour les problèmes de chargement d'assembly, vous devez regarder le tas de chargement avec !eeheap -loader et ensuite inspecter les différents AppDomains que vous avez avec !dumpdomain pour voir quels assemblages vous chargez. Ce ne sont là que quelques exemples - vous devrez fournir plus de détails sur votre situation.

+0

Merci. Je pense que j'ai déjà trouvé la "fuite de mémoire". C'est la fragmentation LOH. N'a pas eu le temps de mettre à jour la question/fournir une réponse à ma propre question. –

Questions connexes