2012-01-26 8 views
21

Se trata de una aplicación de servicio Windows .NET v4 que se ejecuta en una máquina x64. En algún momento, después de varios días de funcionamiento constante, el consumo de memoria de los servicios de Windows se dispara como loco hasta que se cuelga. Pude atraparlo a 1,2 GB y capturar un volcado de memoria. Aquí es lo que consigoCómo analizar el uso de memoria <no clasificado> en windbg

Si corro! Dirijo -summary en windbg en mi archivo de volcado i obtener el resultado seguimiento

! Abordar -summary

--- Usage Summary ------ RgnCount ------- Total Size -------- %ofBusy %ofTotal 
Free      821  7ff`7e834000 ( 7.998 Tb)   99.98% 
<unclassified>   3696  0`6eece000 ( 1.733 Gb) 85.67% 0.02% 
Image     1851  0`0ea6f000 (234.434 Mb) 11.32% 0.00% 
Stack     1881  0`03968000 ( 57.406 Mb) 2.77% 0.00% 
TEB      628  0`004e8000 ( 4.906 Mb) 0.24% 0.00% 
NlsTables    1   0`00023000 (140.000 kb) 0.01% 0.00% 
ActivationContextData 3   0`00006000 ( 24.000 kb) 0.00% 0.00% 
CsrSharedMemory   1   0`00005000 ( 20.000 kb) 0.00% 0.00% 
PEB      1   0`00001000 ( 4.000 kb) 0.00% 0.00% 
- 
- 
- 
--- Type Summary (for busy) -- RgnCount ----- Total Size ----- %ofBusy %ofTotal 
MEM_PRIVATE      5837 0`7115a000 ( 1.767 Gb) 87.34% 0.02% 
MEM_IMAGE       2185 0`0f131000 (241.191 Mb) 11.64% 0.00% 
MEM_MAPPED       40 0`01531000 (21.191 Mb) 1.02% 0.00% 
- 
- 
--- State Summary ------------ RgnCount ------ Total Size ---- %ofBusy %ofTotal 
MEM_FREE       821 7ff`7e834000 ( 7.998 Tb)  99.98% 
MEM_COMMIT       6127 0`4fd5e000 ( 1.247 Gb) 61.66% 0.02% 
MEM_RESERVE      1935 0`31a5e000 (794.367 Mb) 38.34% 0.01% 
- 
- 
--Protect Summary(for commit)- RgnCount ------ Total Size --- %ofBusy %ofTotal 
PAGE_READWRITE      3412 0`3e862000 (1000.383 Mb) 48.29% 0.01% 
PAGE_EXECUTE_READ     220 0`0b12f000 (177.184 Mb) 8.55% 0.00% 
PAGE_READONLY      646 0`02fd0000 ( 47.813 Mb) 2.31% 0.00% 
PAGE_WRITECOPY      410 0`01781000 ( 23.504 Mb) 1.13% 0.00% 
PAGE_READWRITE|PAGE_GUARD   1224 0`012f2000 ( 18.945 Mb) 0.91% 0.00% 
PAGE_EXECUTE_READWRITE    144 0`007b9000 ( 7.723 Mb) 0.37% 0.00% 
PAGE_EXECUTE_WRITECOPY    70 0`001cd000 ( 1.801 Mb) 0.09% 0.00% 
PAGE_EXECUTE       1 0`00004000 ( 16.000 kb) 0.00% 0.00% 
- 
- 
--- Largest Region by Usage ----Base Address -------- Region Size ---------- 
Free       0`8fff0000  7fe`59050000 ( 7.994 Tb) 
<unclassified>     0`80d92000  0`0f25e000 (242.367 Mb) 
Image       fe`f6255000  0`0125a000 ( 18.352 Mb) 
Stack       0`014d0000  0`000fc000 (1008.000 kb) 
TEB        0`7ffde000  0`00002000 ( 8.000 kb) 
NlsTables      7ff`fffb0000  0`00023000 (140.000 kb) 
ActivationContextData   0`00030000  0`00004000 ( 16.000 kb) 
CsrSharedMemory     0`7efe0000  0`00005000 ( 20.000 kb) 
PEB        7ff`fffdd000  0`00001000 ( 4.000 kb) 

En primer lugar, ¿por qué no clasificados espectáculo haría una vez como 1.73 GB y la otra vez como 242 MB. (Esto ha sido contestada. Gracias)

En segundo lugar, entiendo que no clasificada que puede significar código administrado, sin embargo, mi tamaño de la pila de acuerdo a! Eeheap sólo 248 MB, que en realidad coincide con el 242, pero ni siquiera cerca de la 1.73GB. El tamaño del archivo de volcado es de 1.2 GB, que es mucho más alto que lo normal. ¿A dónde voy desde aquí para averiguar qué está usando toda la memoria? Cualquier cosa en el mundo de heap gestionado tiene menos de 248 MB, pero estoy usando 1,2 GB.

Gracias

EDIT

si lo hago! Montón -si sale el siguiente

LFH Key     : 0x000000171fab7f20 
Termination on corruption : ENABLED 
      Heap  Flags Reserv Commit Virt Free List UCR Virt Lock Fast 
          (k)  (k) (k)  (k) length  blocks cont. heap 
------------------------------------------------------------------------------------- 
Virtual block: 00000000017e0000 - 00000000017e0000 (size 0000000000000000) 
Virtual block: 0000000045bd0000 - 0000000045bd0000 (size 0000000000000000) 
Virtual block: 000000006fff0000 - 000000006fff0000 (size 0000000000000000) 
0000000000060000 00000002 113024 102028 113024 27343 1542 11 3 1c LFH 
    External fragmentation 26 % (1542 free blocks) 
0000000000010000 00008000  64  4  64  1  1  1 0 0  
0000000000480000 00001002 3136 1380 3136  20  8  3 0 0 LFH 
0000000000640000 00041002  512  8 512  3  1  1 0 0  
0000000000800000 00001002 3136 1412 3136  15  7  3 0 0 LFH 
00000000009d0000 00001002 3136 1380 3136  19  7  3 0 0 LFH 
00000000008a0000 00041002  512  16 512  3  1  1 0 0  
0000000000630000 00001002 7232 3628 7232  18 53  4 0 0 LFH 
0000000000da0000 00041002 1536 856 1536  1  1  2 0 0 LFH 
0000000000ef0000 00041002 1536 944 1536  4 12  2 0 0 LFH 
00000000034b0000 00001002 1536 1452 1536  6 17  2 0 0 LFH 
00000000019c0000 00001002 3136 1396 3136  16  6  3 0 0 LFH 
0000000003be0000 00001002 1536 1072 1536  5  7  2 0 3 LFH 
0000000003dc0000 00011002  512 220 512 100 60  1 0 2  
0000000002520000 00001002  512  8 512  3  2  1 0 0  
0000000003b60000 00001002 339712 168996 339712 151494 976 116 0 18 LFH 
    External fragmentation 89 % (976 free blocks) 
    Virtual address fragmentation 50 % (116 uncommited ranges) 
0000000003f20000 00001002  64  8  64  3  1  1 0  0  
0000000003d90000 00001002  64  8  64  3  1  1 0  0  
0000000003ee0000 00001002  64  16  64  11  1  1 0  0  
------------------------------------------------------------------------------------- 
+0

Usa el dll de SOS y mira el montón de esa manera. Como se trata de un programa .net, las asignaciones de montón realizadas por .net framework no aparecen en el montón no gestionado. – Zipper

+0

mi tamaño de almacenamiento dinámico de acuerdo con! Eeheap (sos.dll) es de solo 248 MB. Así que no estoy seguro de que esa sea la causa del tamaño del proceso de 1.2 GB, ni la causa de los 1.7 GB en no clasificados, a menos que me falta algo – Mark

+0

¿Qué hace su servicio? ¿Su servicio contiene código no administrado o C++/CLI? Parece una fuga de memoria no administrada. ¿Qué dice el recuento de GDI, objetos del usuario, identificadores? ¿En qué pilas de llamadas están trabadas tus cadenas? ~ * e! ClrStack y ~ * e! DumpStack y ~ * ekv son tus amigos para ver lo que hacían tus hilos. ¿Hay un hilo en el medio de asignar algo? –

Respuesta

2

“Resumen de uso” dice que tiene 3696 regiones no clasificados que dan un total de 17,33 Gb

"Región más grande" indica que la mayor de las regiones no clasificadas es de 242 Mb. El resto de los no clasificados (3695 regiones) juntos hace la diferencia hasta 17,33 Gb.

Trate de hacer un! Heap -s y resumir el Virt col para ver el tamaño de los montones nativos, creo que estos también se cae en el cubo no administrado. (NB versiones anteriores muestra el montón nativo explícito de! Address -summary)

+0

Gracias por la explicación del Resumen de uso frente a la región más grande. ¡He hecho un!heap -s y totalizaron la columna de virt y obtuve 359.12 MB. ¿Eso dice algo? He agregado los resultados de! Heap -s – Mark

+0

No, lo siento, y dado que este es un volcado de 64 bits, no tengo experiencia práctica. Por cierto, ¿de qué versión de .NET es el volcado? Eso podría ser de interés para otros que podrían saber más. –

+0

He agregado esa información en la descripción de la pregunta. Es .NET 4.0 – Mark

1

Lo mejor es usar los comandos EEHeap y GCHandles en windbg (http://msdn.microsoft.com/en-us/ library/bb190764.aspx) y trata de ver si puedes encontrar lo que podría estar filtrando/mal de esa manera.

Desafortunadamente, probablemente no podrá obtener la ayuda exacta que está buscando debido a que el diagnóstico de este tipo de problemas casi siempre requiere mucho tiempo y, fuera de los casos más simples, requiere que alguien haga un completo análisis en el basurero. Básicamente, es poco probable que alguien sea capaz de apuntarle hacia una respuesta directa en el desbordamiento de pila. La mayoría de las personas podrán señalarle comandos que podrían ser útiles. Tendrás que investigar mucho para obtener más información sobre lo que está sucediendo.

+0

Sería lo suficientemente bueno para apuntar en la dirección correcta. Como dije, EEHeap parece describir solo 248 MB de todo el asunto, por lo que no estoy seguro de si la respuesta puede estar ahí. Echaré un vistazo a GCHandles – Mark

16

Recientemente tuve una situación muy similar y encontré algunas técnicas útiles en la investigación. Ninguno es una bala de plata, pero cada uno arroja un poco más de luz sobre el problema.

1) vmmap.exe de SysInternals (http://technet.microsoft.com/en-us/sysinternals/dd535533) hace un buen trabajo al correlacionar información en memoria nativa y administrada y presentarla en una interfaz de usuario agradable. Se puede obtener la misma información usando las técnicas que se encuentran a continuación, pero esto es mucho más fácil y un buen lugar para comenzar. Lamentablemente, no funciona en archivos de volcado, necesita un proceso en vivo.

2) El resultado "! Address -summary" es un resumen de la salida más detallada de "! Address". Me pareció útil dejar caer el resultado detallado en Excel y ejecutar algunos pivotes. Al utilizar esta técnica, descubrí que una gran cantidad de bytes que se enumeraban como "" eran en realidad MEM_IMAGE páginas, probablemente copias de páginas de datos que se cargaron cuando se cargaron las DLL pero luego se copiaron cuando se modificaron los datos. También podría filtrar a regiones grandes y profundizar en direcciones específicas. Hurgar en el basurero de memoria con un mondadientes y rezar mucho es doloroso, pero puede ser revelador.

3) Finalmente, hice una versión pobre de la técnica vmmap.exe anterior. Cargué el archivo de volcado, abrí un registro y ejecuté la dirección,! Eeheap,! Heap y! Thread. También me centré en los bloques de entorno de subprocesos enumerados en ~ * k con! Teb. Cerré el archivo de registro y lo cargué en mi editor favorito. Pude encontrar un bloque no clasificado y buscar para ver si aparecía en el resultado de uno de los comandos más detallados. Puede correlacionar bastante rápidamente los montones nativos y gestionados para eliminar aquellos de las regiones sospechosas no clasificadas.

Estos son demasiado manuales. Me encantaría escribir una secuencia de comandos que tomaría el resultado similar a lo que generé en la técnica 3 anterior y producir un archivo mmp adecuado para ver el archivo vmmap.exe. Algún día.

Una última nota: hice una correlación entre el resultado de vmmap.exe con la salida de dirección! Y anoté estos tipos de regiones identificadas por vmmap couple de varias fuentes (¡similar a qué! Heap y! Eeheap usan) pero esa dirección no sabía nada Es decir, estas son cosas que vmmap.exe marcada, pero no lo hizo Dirección:

.data 
.pdata 
.rdata 
.text 
64-bit thread stack 
Domain 1 
Domain 1 High Frequency Heap 
Domain 1 JIT Code Heap 
Domain 1 Low Frequency Heap 
Domain 1 Virtual Call Stub 
Domain 1 Virtual Call Stub Lookup Heap 
Domain 1 Virtual Call Stub Resolve Heap 
GC 
Large Object Heap 
Native heaps 
Thread Environment Blocks 

todavía había una gran cantidad de "privado" bytes en paradero desconocido, pero de nuevo, yo soy capaz de reducir el problema si Puedo eliminarlos.

Espero que esto te brinde algunas ideas sobre cómo investigar. Estoy en el mismo barco, así que apreciaría lo que encuentres también. ¡Gracias!

+0

"Me encantaría escribir un script ... para ver el vmmap": ¿has tenido la oportunidad de hacerlo? –

1

guardo una copia de las herramientas de depuración para Windows 6.11.1.404 que parece ser capaz de mostrar algo más significativo para los "sin clasificar"

Con esa versión, veo una lista de direcciones de TEB y luego esto:

0:000> !address -summary 
--------- PEB fffde000 not found ---- 
TEB fffdd000 in range fffdb000 fffde000 
TEB fffda000 in range fffd8000 fffdb000 
...snip... 
TEB fe01c000 in range fe01a000 fe01d000 
ProcessParametrs 002c15e0 in range 002c0000 003c0000 
Environment 002c0810 in range 002c0000 003c0000 
-------------------- Usage SUMMARY -------------------------- 
    TotSize (  KB) Pct(Tots) Pct(Busy) Usage 
    41f08000 (1080352) : 25.76% 34.88% : RegionUsageIsVAD 
    42ecf000 (1096508) : 26.14% 00.00% : RegionUsageFree 
    5c21000 ( 94340) : 02.25% 03.05% : RegionUsageImage 
    c900000 ( 205824) : 04.91% 06.64% : RegionUsageStack 
      0 (  0) : 00.00% 00.00% : RegionUsageTeb 
    68cf8000 (1717216) : 40.94% 55.43% : RegionUsageHeap 
      0 (  0) : 00.00% 00.00% : RegionUsagePageHeap 
      0 (  0) : 00.00% 00.00% : RegionUsagePeb 
      0 (  0) : 00.00% 00.00% : RegionUsageProcessParametrs 
      0 (  0) : 00.00% 00.00% : RegionUsageEnvironmentBlock 
     Tot: ffff0000 (4194240 KB) Busy: bd121000 (3097732 KB) 

-------------------- Type SUMMARY -------------------------- 
    TotSize (  KB) Pct(Tots) Usage 
    42ecf000 (1096508) : 26.14% : <free> 
    5e6e000 ( 96696) : 02.31% : MEM_IMAGE 
    28ed000 ( 41908) : 01.00% : MEM_MAPPED 
    b49c6000 (2959128) : 70.55% : MEM_PRIVATE 

-------------------- State SUMMARY -------------------------- 
    TotSize (  KB) Pct(Tots) Usage 
    9b4d1000 (2544452) : 60.67% : MEM_COMMIT 
    42ecf000 (1096508) : 26.14% : MEM_FREE 
    21c50000 ( 553280) : 13.19% : MEM_RESERVE 

Largest free region: Base bc480000 - Size 38e10000 (931904 KB) 

Con mi versión "actual" (6.12.2.633) obtengo esto del mismo vertedero. Dos cosas que noto:

Los datos parecen ser la suma de HeapAlloc/RegionUsageHeap y VirtualAlloc/RegionUsageIsVAD).

¡El encantador error EFAIL que sin duda es en parte responsable de los datos faltantes!

no estoy seguro de cómo se va a ayudar con el código administrado, pero creo que en realidad responde a la pregunta original ;-)

0:000> !address -summary 


Failed to map Heaps (error 80004005) 

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
<unclassified>       7171   aab21000 ( 2.667 Gb) 90.28% 66.68% 
Free         637   42ecf000 ( 1.046 Gb)   26.14% 
Stack         603   c900000 (201.000 Mb) 6.64% 4.91% 
Image         636   5c21000 ( 92.129 Mb) 3.05% 2.25% 
TEB          201    c9000 (804.000 kb) 0.03% 0.02% 
ActivationContextData     14    11000 ( 68.000 kb) 0.00% 0.00% 
CsrSharedMemory       1    5000 ( 20.000 kb) 0.00% 0.00% 

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
MEM_PRIVATE       7921   b49c6000 ( 2.822 Gb) 95.53% 70.55% 
MEM_IMAGE        665   5e6e000 ( 94.430 Mb) 3.12% 2.31% 
MEM_MAPPED        40   28ed000 ( 40.926 Mb) 1.35% 1.00% 

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
MEM_COMMIT        5734   9b4d1000 ( 2.427 Gb) 82.14% 60.67% 
MEM_FREE        637   42ecf000 ( 1.046 Gb)   26.14% 
MEM_RESERVE       2892   21c50000 (540.313 Mb) 17.86% 13.19% 

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
PAGE_READWRITE       4805   942bd000 ( 2.315 Gb) 78.37% 57.88% 
PAGE_READONLY       215   3cbb000 ( 60.730 Mb) 2.01% 1.48% 
PAGE_EXECUTE_READ      78   2477000 ( 36.465 Mb) 1.21% 0.89% 
PAGE_WRITECOPY       74   75b000 ( 7.355 Mb) 0.24% 0.18% 
PAGE_READWRITE|PAGE_GUARD    402   3d6000 ( 3.836 Mb) 0.13% 0.09% 
PAGE_EXECUTE_READWRITE     80   3b0000 ( 3.688 Mb) 0.12% 0.09% 
PAGE_EXECUTE_WRITECOPY     80   201000 ( 2.004 Mb) 0.07% 0.05% 

--- Largest Region by Usage ----------- Base Address -------- Region Size ---------- 
<unclassified>        786000   17d9000 ( 23.848 Mb) 
Free          bc480000   38e10000 (910.063 Mb) 
Stack          6f90000    fd000 (1012.000 kb) 
Image          3c3c000   ebe000 ( 14.742 Mb) 
TEB           fdf8f000    1000 ( 4.000 kb) 
ActivationContextData       190000    4000 ( 16.000 kb) 
CsrSharedMemory        7efe0000    5000 ( 20.000 kb) 
0

Recientemente he pasado algún tiempo el diagnóstico de un problema de los clientes en los que su la aplicación estaba usando 70 GB antes de finalizar (probablemente debido a un límite de reciclaje de la lista de aplicaciones de IIS, pero aún no confirmada). Me enviaron un volcado de memoria de 35 GB. Basado en mi experiencia reciente, he aquí algunas observaciones que puedo hacer sobre lo que ha proporcionado:

En la salida! Heap -s, se muestran 284 MB de los 1.247 GB en la columna Commit. Si tuviera que abrir este volcado en DebugDiag, le diría que el montón 0x60000 tiene 1 GB de memoria comprometida.Sumará el tamaño de confirmación de los 11 segmentos informados y descubrirá que solo suman aproximadamente 102 MB y no 1 GB. Muy molesto.

No falta la memoria "faltante". De hecho, se insinúa en la salida! Heap -s como líneas "Virtual block:". ! Por desgracia, montón -s chupa y no muestra la dirección final, y en consecuencia informa tamaño que 0. Compruebe la salida de los comandos siguientes:

!address 17e0000 
!address 45bd0000 
!address 6fff0000 

Se informará la dirección final adecuada y por lo tanto una precisa " Tamaño de la región ". Aún mejor, da una versión sucinta del tamaño de la región. Si agrega el tamaño de esas 3 regiones a 102 MB, debería estar bastante cerca de 1 GB.

¿Qué hay en ellas? Bueno, puedes mirar usando dq. Por espeleología, puede encontrar una pista de por qué fueron asignados. Tal vez su código administrado llame a un código de terceros que tenga un lado nativo.

Es posible que pueda encontrar referencias a su pila utilizando !heap 6fff0000 -x -v. Si hay referencias, puede ver en qué regiones de memoria viven usando la dirección! En mi problema con el cliente encontré una referencia que vivía en una región con "Uso: Pila". Una sugerencia de "Más información:" hacía referencia al hilo de la pila que tenía algunas grandes llamadas anexar/copiar de cadena básica en la parte superior.

Cuestiones relacionadas