2010-07-08 12 views
10

Sto cercando di rintracciare perché una stringa è archiviata così a lungo nella mia applicazione e consuma una quantità eccessiva di memoria. Ho un servizio di Windows che viene eseguito regolarmente.WinDbg non mi dice dove è radicata la mia stringa

Legge i dati da un database (sotto forma di un DataSet) e quindi esegue qualche elaborazione, tutto gestito da .NET.

Il servizio di Windows viene attivato una volta ogni 5 minuti circa, il che fa alcuni riferimenti incrociati. Ogni riga del DataSet non dovrebbe richiedere molto più di un secondo - il caso peggiore!

A un livello i byte privati> 1,2 GB, anche se non erano disponibili dati da elaborare. Non ci sono variabili globali e tutte le elaborazioni avvengono all'interno dei singoli metodi.

Ho scattato un'istantanea ed elaborato con WinDbg. Ecco i risultati:

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 

E così vogliamo trovare i 2 stringhe che sono la causa del problema:

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 

Ora voglio scoprire dove si trovano questi 2, ma quando uso ! gcroot, non restituisce alcun risultato:

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 

non capisco quello che sto facendo male, o perché la radice del stringa non può essere trovato. Ho fatto fare su di esso, e si dice solo le stringhe sono stampabili:

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

E

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

qualcuno può aiutarmi per favore?

-

Aggiornamento:

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) 

Update 2: ho rimosso i riferimenti a XML come questo particolare programma non elabora XML - il mio male!.


Update 3:

Ecco i risultati dell'utilizzo di 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

Come è possibile che si dispone di un valore di stringa che è 512 MB grande? Potresti usare XMLReader per leggere i dati invece? –

risposta

7

CURA (D'oh, più caffè richiesto) Queste stringhe sono più grandi di 85.000 byte in modo risiederanno nell'heap di oggetti di grandi dimensioni che raramente viene raccolto e non compattato (con conseguente frammentazione, soprattutto se si stanno allocando molti oggetti di grandi dimensioni a breve durata).

Ciò che WinDbg sta dicendo è corretto - questi non hanno una radice e sono spazzatura, ma poiché sono sul LOH potrebbero non essere eliminati rapidamente (se non del tutto).

È sicuramente necessario ripensare a come si sta elaborando l'XML, cercare i dati di streaming in/out piuttosto che caricare/creare in memoria in anticipo.

+0

Quindi stai dicendo che nessun oggetto residente nel LOH non può essere trovato usando WinDBG? Come ho un array di byte 226 MB che non sono sicuro di entrambi? –

+0

Riedita la mia risposta quando mi sono reso conto che stavo dicendo sciocchezze sul LOH che non veniva raccolto (non è * compattato *). WinDBG sta trovando gli oggetti sul tuo LOH fine, per quanto posso vedere, il problema è che gli oggetti inutili non vengono raccolti rapidamente perché sono sul LOH, il tuo ultimo aggiornamento lo mostra in netto contrasto. – Paolo

+0

Quindi, quando diciamo "senza radici", intendiamo solo oggetti che non sono più referenziati, ma nel mio caso non sono stati raccolti dalla spazzatura? –

1

Gli oggetti in LOH verranno raccolti solo quando è presente una pressione di memoria. GC raccoglie oggetti in LOH solo quando esegue una raccolta completa.

Il psscor2.dll (estensione per eseguire il debug di codice gestito) ha un comando

!HeapStat [-inclUnrooted | -iu] 

che il dump solo radici valide, rispetto al !eeheap

Problemi correlati