2010-07-08 12 views
10

Estoy intentando rastrear por qué una cadena se almacena tanto tiempo en mi aplicación, y consumir una cantidad excesiva de memoria. Tengo un servicio de Windows que se ejecuta regularmente.WinDbg no me dice dónde está rooteada mi cadena

Lee los datos de una base de datos (en forma de un conjunto de datos) y luego procesa - todos administrados .NET.

El servicio de Windows se activa una vez cada 5 minutos aproximadamente, lo que hace referencia cruzada. Cada fila del DataSet no debería tomar mucho más que un segundo - ¡el peor caso!

En una etapa, los Bytes privados> 1.2GB, aunque no había datos disponibles para procesar. No hay variables globales, y todo el procesamiento se realiza dentro de los métodos individuales.

Tomé una instantánea y la procesé con WinDbg. Aquí están los resultados:

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 

Y así queremos encontrar las 2 cadenas que están causando el 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 

Ahora quiero averiguar dónde se encuentran estos 2, pero cuando uso ! gcroot, que no devuelve ningún resultado:

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 

no entiendo lo que estoy haciendo mal, o por qué la raíz de la cadena no se puede encontrar. He hecho hacer en él, y que sólo se dice que las cadenas son imprimibles:

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

Y

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

Alguien puede ayudar por favor?

-

Actualización:

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) 

Actualización 2: He quitado las referencias a XML como este programa en particular no procesa XML - mi mal!.


Actualización 3:

Aquí es los resultados del uso 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

¿Cómo es que tiene un valor de cadena que es 512 MB grande? ¿Podría usar XMLReader para leer los datos en su lugar? –

Respuesta

7

EDITADO (D'oh, requiere más café) Estas cadenas son más grandes que 85.000 bytes por lo residirán en el gran montón de objetos que rara vez se recoge y no se compacta (lo que lleva a la fragmentación, especialmente si se asignan muchos objetos grandes de corta duración).

Lo que WinDbg te dice es correcto: no tienen raíz y son basura, pero como están en LOH, es posible que no se eliminen rápidamente (si es que lo hacen).

Definitivamente tiene que volver a pensar cómo está procesando el XML, ver los datos de transmisión de entrada/salida en lugar de cargar/crear en la memoria por adelantado.

+0

Entonces, ¿está diciendo que no se puede encontrar ningún objeto que resida en el LOH usando WinDBG? Como tengo una matriz de bytes de 226 MB de la que tampoco estoy seguro? –

+0

Volví a editar mi respuesta ya que me di cuenta de que estaba diciendo tonterías acerca de que LOH no se recopila (no está * compactado *). WinDBG está encontrando los objetos en su LOH bien por lo que puedo ver, el problema es que los objetos basura no se recogen rápidamente porque están en el LOH, su última actualización muestra eso en absoluto alivio. – Paolo

+0

Entonces, cuando decimos sin raíz, solo nos referimos a objetos a los que ya no se hace referencia, pero en mi caso no se han recogido basura. –

1

Los objetos en LOH se recogerán solo cuando haya memoria de presión. GC recolectaría objetos en LOH solo cuando está haciendo una colección completa.

El psscor2.dll (extensión para depurar código administrado) tiene un comando

!HeapStat [-inclUnrooted | -iu] 

que volcar sólo las raíces válidos, en comparación con !eeheap

Cuestiones relacionadas