2010-07-08 16 views
10

J'essaie de savoir pourquoi une chaîne est stockée si longtemps dans mon application, et de manger une quantité excessive de mémoire. J'ai un service Windows qui fonctionne régulièrement.WinDbg ne me dit pas où ma chaîne est enracinée

Il lit les données à partir d'une base de données (sous la forme d'un DataSet), puis effectue un traitement - tous gérés .NET.

Le service Windows est déclenché toutes les 5 minutes environ, ce qui entraîne des références croisées. Chaque rangée du DataSet ne devrait pas prendre beaucoup plus d'une seconde - le pire des cas! À un moment, les octets privés> 1,2 Go, même s'il n'y avait pas de données disponibles à traiter. Il n'y a pas de variables globales et tout le traitement est effectué dans des méthodes individuelles. J'ai pris un instantané et traité avec WinDbg.

Voici les résultats:

0:000> !dumpheap -min 85000 
Address  MT  Size 
02027f40 00166620 101432 Free 
28411000 79330b24 536870936  
48c11000 79333594 226273040  
08411000 79330b24 452546504  
total 4 objects 
Statistics: 
     MT Count TotalSize Class Name 
00166620  1  101432  Free 
79333594  1 226273040 System.Byte[] 
79330b24  2 989417440 System.String 
Total 4 objects 

Et nous voulons trouver les 2 chaînes qui sont à l'origine du problème:

0:000> !dumpheap -mt 79330b24 -min 85000 
Address  MT  Size 
28411000 79330b24 536870936  
08411000 79330b24 452546504  
total 2 objects 
Statistics: 
     MT Count TotalSize Class Name 
79330b24  2 989417440 System.String 
Total 2 objects 

Maintenant, je veux savoir où ces deux sont situés, mais quand je l'utilise ! gcroot, il ne renvoie aucun résultat:

0:000> !gcroot 28411000 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for 
more info. 
Scan Thread 0 OSTHread 2970 
Scan Thread 2 OSTHread 2ab4 
Scan Thread 3 OSTHread 12ac 
Scan Thread 4 OSTHread 1394 
Scan Thread 5 OSTHread 1b78 
Scan Thread 8 OSTHread 1364 
Scan Thread 9 OSTHread 226c 
Scan Thread 10 OSTHread 1694 
0:000> !gcroot 08411000 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for 
more info. 
Scan Thread 0 OSTHread 2970 
Scan Thread 2 OSTHread 2ab4 
Scan Thread 3 OSTHread 12ac 
Scan Thread 4 OSTHread 1394 
Scan Thread 5 OSTHread 1b78 
Scan Thread 8 OSTHread 1364 
Scan Thread 9 OSTHread 226c 
Scan Thread 10 OSTHread 1694 

Je ne comprends pas ce que je fais mal, ou pourquoi ne peut trouver la racine de la chaîne. Je l'ai fait faire à ce sujet, et il dit que les chaînes sont unprintable:

0:000> !do 28411000 
Name: System.String 
MethodTable: 79330b24 
EEClass: 790ed65c 
Size: 536870930(0x20000012) bytes 
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) 
String: <String is invalid or too large to print> 

Fields: 
     MT Field Offset     Type VT  Attr Value Name 
79332d70 4000096  4   System.Int32 0 instance 268435457 m_arrayLength 
79332d70 4000097  8   System.Int32 0 instance 226273026 m_stringLength 
79331804 4000098  c   System.Char 0 instance  57 m_firstChar 
79330b24 4000099  10  System.String 0 shared static Empty 
    >> Domain:Value 00159f38:01021198 << 
79331754 400009a  14  System.Char[] 0 shared static WhitespaceChars 
    >> Domain:Value 00159f38:010217d4 << 

Et

0:000> !do 08411000 
Name: System.String 
MethodTable: 79330b24 
EEClass: 790ed65c 
Size: 452546502(0x1af94fc6) bytes 
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) 
String: <String is invalid or too large to print> 

Fields: 
     MT Field Offset     Type VT  Attr Value Name 
79332d70 4000096  4   System.Int32 0 instance 226273243 m_arrayLength 
79332d70 4000097  8   System.Int32 0 instance 226273242 m_stringLength 
79331804 4000098  c   System.Char 0 instance  45 m_firstChar 
79330b24 4000099  10  System.String 0 shared static Empty 
    >> Domain:Value 00159f38:01021198 << 
79331754 400009a  14  System.Char[] 0 shared static WhitespaceChars 
    >> Domain:Value 00159f38:010217d4 << 

aide quelqu'un peut s'il vous plaît?

-

Mise à jour:

eeheap -gc

Number of GC Heaps: 1 
generation 0 starts at 0x01175764 
generation 1 starts at 0x011756dc 
generation 2 starts at 0x01021000 
ephemeral segment allocation context: none 
segment begin allocated  size 
01020000 01021000 0117b770 0x0015a770(1419120) 
Large object heap starts at 0x02021000 
segment begin allocated  size 
02020000 02021000 02040d88 0x0001fd88(130440) 
28410000 28411000 48411018 0x20000018(536870936) 
48c10000 48c11000 563db710 0x0d7ca710(226273040) 
08410000 08411000 233a5fc8 0x1af94fc8(452546504) 
Total Size 0x488d9be8(1217240040) 
------------------------------ 
GC Heap Size 0x488d9be8(1217240040) 

Mise à jour 2: J'ai supprimé les références à XML que ce programme ne traite pas XML - mon mauvais!.


Mise à jour 3:

Voici les résultats de l'utilisation psscor2.dll

0:000> !heapstat -inclUnrooted 
Heap  Gen0   Gen1   Gen2   LOH 
Heap0 32780  68316  1324728  1217845888 

Free space:             Percentage 
Heap0 12   67212  59764  101640  SOH: 8% LOH: 0% 

Unrooted objects:           Percentage 
Heap0 2684   1104   757416  1217715448 SOH: 53% LOH: 99% 
+0

Comment est-ce que vous avez une valeur de chaîne qui est 512 MB grand? Pourriez-vous utiliser XMLReader pour lire les données à la place? –

Répondre

7

ÉDITÉ (D'oh, plus de café nécessaire) Ces chaînes sont plus grandes que 85.000 octets afin ils resteront sur le gros tas d'objets qui est rarement ramassé et non compacté (ce qui conduit à la fragmentation, surtout si vous allouez beaucoup d'objets volumineux de courte durée). Ce que WinDbg vous dit est correct - ceux-ci n'ont pas de racine et ils sont corrompus, mais parce qu'ils sont sur le LOH, ils peuvent ne pas être effacés rapidement (voire pas du tout).

Vous avez certainement besoin de repenser la façon dont vous traitez le XML, regardez le flux de données en entrée/sortie plutôt que de charger/créer en mémoire à l'avance.

+0

Donc, vous dites que tout objet résidant sur le LOH ne peut pas être trouvé en utilisant WinDBG? Comme j'ai un tableau de 226 Mo d'octets dont je ne suis pas sûr non plus? –

+0

Réédité ma réponse comme je me suis rendu compte que je disais des bêtises au sujet de la LOH n'est pas recueillie (ce n'est pas * compacté *). WinDBG trouve les objets sur votre LOH bien autant que je peux voir, le problème est que les objets de poubelle ne sont pas collectés rapidement parce qu'ils sont sur le LOH, votre dernière mise à jour montre cela en relief. – Paolo

+0

Donc quand nous disons non raclée, nous voulons simplement dire des objets qui ne sont plus référencés, mais dans mon cas, ils n'ont pas été ramassés? –

1

Les objets dans LOH ne seront collectés que s'il y a une pression de mémoire. GC ne collecterait des objets dans LOH que lorsqu'il effectuera une collection complète.

Le psscor2.dll (extension de débogage du code managé) a une commande

!HeapStat [-inclUnrooted | -iu] 

qui déchargera que les racines valides, par rapport à !eeheap