debugging memory windbg unmanaged

debugging - Cómo analizar el uso de memoria<unclassified> en windbg



memory unmanaged (5)

Esta es una aplicación de servicio de Windows .NET v4 que se ejecuta en una máquina x64. En algún momento, después de días de funcionamiento constante, el consumo de memoria del servicio de Windows se disparó hasta que se bloqueó. Pude atraparlo a 1.2 GB y capturar un volcado de memoria. Esto es lo que obtengo

Si ejecuto! Address -summary en windbg en mi archivo de volcado obtengo el siguiente resultado

! dirección -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é los programas sin clasificar se mostrarán una vez como 1.73 GB y la otra como 242 MB? (Esto ha sido respondido. Gracias)

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

Gracias

EDITAR

Si lo hago! Heap -si obtengo lo 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 -------------------------------------------------------------------------------------


El "resumen de uso" indica que tiene 3696 regiones sin clasificar, lo que da un total de 17.33 Gb

"Región más grande" indica que la región más grande sin clasificar es de 242 Mb. El resto de los no clasificados (3695 regiones) juntos hacen la diferencia hasta 17.33 Gb.

Intente hacer un! Heap –s y resumir la columna Virt para ver el tamaño de los montones nativos, creo que estos también caen en el cubo no administrado. (Nota: las versiones anteriores muestran el montón nativo explícito de! Address -summary)


Guardo una copia de las herramientas de depuración para Windows 6.11.1.404 que parece poder mostrar algo más significativo para "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) recibo esto del mismo volcado. Dos cosas que observo:

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 eso lo ayudará con su 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)


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

Lamentablemente, es probable que no pueda obtener la ayuda exacta que está buscando, ya que el diagnóstico de este tipo de problemas casi siempre requiere mucho tiempo y, aparte de los casos más simples, es necesario que alguien realice un análisis completo del volcado. . Básicamente, es poco probable que alguien pueda dirigirte 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á que investigar mucho para encontrar más información sobre lo que está sucediendo.


Recientemente dediqué un tiempo a diagnosticar un problema de los clientes en el que su aplicación utilizaba 70 GB antes de terminar (probablemente debido a que alcanzó un límite de reciclaje del grupo de aplicaciones de IIS, pero aún no se ha confirmado). Me enviaron un volcado de memoria de 35 GB. En base a mi experiencia reciente, aquí hay algunas observaciones que puedo hacer acerca de lo que has proporcionado:

En la salida de! 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. Agregará el tamaño de compromiso de los 11 segmentos informados y encontrará que solo suman aproximadamente 102 MB y no 1 GB. Muy molesto.

No falta la memoria "faltante". En realidad, se insinúa en la salida de! Heap -s como líneas de "bloque virtual:". Desafortunadamente,! Heap -s apesta y no muestra la dirección final correctamente y, por lo tanto, informa que el tamaño es 0. Compruebe la salida de los siguientes comandos:

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

Informará la dirección final correcta y, por lo tanto, un "Tamaño de región" preciso. 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, debe estar cerca de 1 GB.

Entonces, ¿qué hay en ellos? Bueno, puedes mirar usando dq. Al espiar, es posible que encuentres una pista sobre por qué se asignaron. Quizás su código administrado llama a un código de terceros que tiene un lado nativo.

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


Recientemente tuve una situación muy similar y encontré un par de técnicas útiles en la investigación. Ninguna es una bala de plata, pero cada una 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 la información en la memoria nativa y administrada y presentarla en una interfaz de usuario agradable. La misma información se puede recopilar utilizando las técnicas a continuación, pero 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) La salida "! Address -summary" es un resumen de la salida más detallada de "! Address". Me pareció útil colocar el resultado detallado en Excel y ejecutar algunos pivotes. Usando esta técnica, descubrí que una gran cantidad de bytes que se enumeraban como "" eran en realidad páginas MEM_IMAGE, probablemente copias de páginas de datos que se cargaron cuando se cargaron los DLL pero luego se copiaron cuando se cambiaron los datos. También podría filtrar a grandes regiones y profundizar en direcciones específicas. Hurgando en el volcado de memoria con un palillo de dientes y mucha oración es doloroso, pero puede ser revelador.

3) Finalmente, hice la versión de un hombre pobre de la técnica vmmap.exe anterior. Cargué el archivo de volcado, abrí un registro y corrí la dirección,! Eeheap,! Heap y! Threads. También apunté a los bloques de entorno de subprocesos listados en ~ * k con! Teb. Cerré el archivo de registro y lo cargué en mi editor favorito. Luego podría encontrar un bloque sin clasificar y buscar si aparecía en la salida de uno de los comandos más detallados. Puede correlacionar rápidamente montones nativos y administrados para eliminar aquellos de sus regiones no clasificadas sospechosas.

Todos estos son demasiado manuales. Me encantaría escribir una secuencia de comandos que tome la salida similar a la que generé en la técnica 3 anterior y generaría un archivo mmp adecuado para ver el vmmap.exe. Algún día.

Una última nota: hice una correlación entre la salida de vmmap.exe con la salida de! Address y noté estos tipos de regiones que las parejas de vmmap identifican de varias fuentes (de forma similar a lo que! Heap y! Eeheap use) pero esa dirección no sabía acerca de. Es decir, estas son cosas que vmmap.exe etiquetó pero la dirección no:

.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 muchos bytes "privados" que no se contabilizaban, pero, de nuevo, soy capaz de reducir el problema si puedo eliminarlos.

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