Red de conocimiento informático - Aprendizaje de programación - Método de análisis y diagnóstico de Out Of Memory

Método de análisis y diagnóstico de Out Of Memory

En primer lugar, ¿qué es Out Of Memory? El desbordamiento de memoria se abrevia como OOM (¡usaré esta abreviatura a continuación!). Para decirlo sin rodeos, cuando el programa quiere usar memoria, el sistema operativo no tiene tanta memoria para asignar y luego ocurre un error de OOM.

Antes que nada, permítanme presentarme. La situación de este proyecto se basa en la llamada al servicio web Exchange sp hmc. Utiliza un programa de prueba de simulación winform para agregar información en un solo hilo y realizar bucles miles de veces. empresa y abre un nombre de dominio de correo electrónico y crea una cuenta. Cada cuenta abre el servicio de correo electrónico. Ahora se repite aproximadamente cuando la ocupación de memoria de wwp exe es bytes privados M bytes virtuales M. Escuché de mis hermanos que han hecho algo similar. pruebas Cuando el bucle llega a la herramienta súper genial debugdiag. (Esta herramienta se presentará más adelante porque es realmente doloroso publicar N muchas imágenes...) Use debugdiag para capturar el volcado de pérdida de memoria (M) y encontró el siguiente problema: mscorwks filtró información sobre la memoria M

Ahora ve a windbg. ¡Veamos primero los comandos! eeheap tiene dos parámetros

gt; ayuda eeheap

 

! EEHeap [ gc] [ loader]

¡Primero, eche un vistazo a los parámetros de gc! eeheap gc Este comando indica el tamaño del montón administrado ocupado por nuestro programa

> gt; eeheap gc

Número de montones de GC

La generación comienza en x ff f

La generación comienza en x f df c

La generación comienza en x c

contexto de asignación de segmento efímero (x bcbf x bd c)

tamaño asignado de inicio del segmento

ead a c c a d x edc ( )

e a d a f b x f b ( )

  c c bd c x fc c( )

 El montón de objetos grandes comienza en x c

 el segmento comienza con el tamaño asignado

  c c cfbbd x abd ( )

Tamaño total xa d ( )

Tamaño del montón de GC xa d ( )

El tamaño del volcado es M Tamaño del montón administrado ¡Hay una gran diferencia para M! ¿Dónde está el resto del recuerdo? ¡Ahora veamos un nuevo comando! Después de ejecutar la dirección, habrá una gran cantidad de resultados. Lo que nos importa es el siguiente resumen.

RESUMEN de uso

TotSize (KB) Pct (Tots) Pct (Ocupado) Uso

p>

b ( ) RegionUsageIsVAD

c b ( ) RegionUsageFree

d ( ) RegionUsageImage

fc ( ) RegionUsageStack

( ) RegionUsageTeb

( ) RegionUsageHeap

 ( ) RegionUsagePageHeap

  ( ) RegionUsagePeb

  ( ) RegionUsageProcessParametrs

  ( ) RegionUsageEnvironmentBlock

 Tot fff (KB) Ocupado b c (KB)

RESUMEN de tipo

TotSize (KB) Pct (Tots) Uso

c b ( ) lt freegt; ( ) MEM_IMAGE

a ( ) MEM_MAPPED

a d ( ) MEM_PRIVATE

Estado RESUMEN

TotSize (KB) Pct (Tots) Uso

ee ( ) MEM_MIT

c b ( ) MEM_FREE

ca ( ) MEM_RESERVE

La información anterior es más interesante que RegionUsageImage representa archivos DLL. La memoria ocupada es M. RegionUsageheap representa montones de NT. La memoria ocupada es M. La suma de MEM_MIT y MEM_RESERVE es memoria virtual. El total de ellos es M. ¿Qué nos hemos perdido? ! Hay otro parámetro de eeheap, que es el cargador. Después de ejecutarlo, habrá N resultados largos. ¡Echemos un vistazo a una parte

! eeheap –loader

Dominio fbd

LowFrequencyHeap ba ( ) d ( ) ee ( ) b ( ) ea ( ) f ( f ) ( ) Muy amarillo y violento... edc ( ) ee ( ) Tamaño x ce ( ) bytes

X ( ) bytes desperdiciados

HighFrequencyHeap ba ( ) e ( f ) aa ( ) c ( f ) ( ) ( ) d ( ) Eba muy amarillo y violento ( ) ee ( ) Tamaño x a ( ) bytes

Desperdiciado x ( ) bytes

StubHeap baa ( ) Tamaño x ( ) bytes

Montón de código auxiliar de llamadas virtuales

Tamaño de IndcellHeap x ( ) bytes

Tamaño de LookupHeap x ( ) bytes

Tamaño de ResolveHeap x ( ) bytes

Tamaño de DispatchHeap x ( ) bytes

p>

CacheEntryHeap bc ( ) Tamaño x ( ) bytes

Tamaño total x c ( ) bytes

Una *** memoria M ocupada Continúe leyendo el siguiente contenido. y descubrí ¡Tengo un módulo! ! !

 Montones de procesadores de módulo

 Tamaño de módulo aa x ( ) bytes

 Tamaño de módulo e x ( ) bytes

 Tamaño de módulo a x ( ) bytes

Tamaño del módulo x ( ) bytes

============= Muy pornográfico y violento =========== ===========

 Tamaño del módulo ee x ( ) bytes

 Tamaño del módulo ee x ( ) bytes

 Tamaño del módulo ee c x ( ) bytes

Tamaño del módulo ee c x ( ) bytes

Tamaño total x ( ) bytes

Tamaño total de LoaderHeap x a f ( ) bytes

========================================= ==

¡El problema básicamente ha surgido! ¡Hay casi 10,000 módulos en la memoria! ¡Simplemente tírelo y vea si hay otro comando aquí! dumpmodule

¡Simplemente descargue uno y vea información similar a la siguiente

gt; dumpmodule ee

Nombre qrt x cw Versión= Cultura=neutral PublicKeyToken=null

Atributos PEFile

Ensamblaje cf e

LoaderHeap

LoaderHeap

p>

p>

TypeDefToMethodTableMap edcc

TypeRefToMethodTableMap edcc c

MethodDefToDescMap edcc c

FieldDefToDescMap edcc

MemberRefToDescMap edcc c

FileReferencesMap edcc

AssemblyReferencesMap edcc

Dirección inicial de metadatos ed (bytes)

Es posible que no veas nada aquí, así que agreguemos un parámetro mt para echarle un vistazo

gt;! dumpmodule mt ee

Nombre qrt x cw Versión= Cultura=neutral PublicKeyToken=null

Atributos PEFile

Ensamblaje cf e

LoaderHeap

TypeDefToMethodTableMap e

dcc

TypeRefToMethodTableMap edcc c

MethodDefToDescMap edcc c

FieldDefToDescMap edcc

MemberRefToDescMap edcc c

FileReferencesMap edcc

 AssemblyReferencesMap edcc

 Dirección inicial de metadatos ed (bytes)

 Tipos definidos en este módulo

 MT TypeDef Name

ee c x Serialización Xml de Microsoft GeneratedAssembly XmlSerializationReaderCreateUserResponseData

ee c x Serialización Xml de Microsoft GeneratedAssembly Nombre

 

  e eac x Serialización Xml del sistema XmlSerializationReader

  e b x Serialización Xml del sistema >

e be x System Xml XmlReader

fd cc x Tabla hash de colecciones del sistema

f a x e Objeto del sistema

e c x System Xml XmlQualifiedName

c x System Boolean

e a b x System Xml XmlNameTable

Aparece la serialización de System Xml. Pasemos a la pila de llamadas analizada por debugdiag

Muestra de pila de llamadas

Dirección x c

Tiempo de asignación desde que comenzó el seguimiento

Tamaño de asignación en bytes

Función Fuente Destino

mscorjit! norls_allocator nraAllocNewPage

mscorjit! norls_allocator nraAlloc mscorjit! norls_allocador

nraAllocNewPage

mscorjit! jitNativeCode mscorjit! norls_allocator nraAlloc

mscorjit! CILJit pileMétodo d mscorjit! jitNativeCode

x E C E

mscorjit! Compilador impExpandInline aa

mscorjit! Compilador fgMorphTree

mscorjit! Compilador fgMorphStmts mscorjit! Compilador fgMorphTree

mscorjit! Compilador fgMorphBlocks mscorjit! Compilador fgMorphStmts

mscorjit! Compilador fgMorph mscorjit! Compilador fgMorphBlocks

mscorjit! Compilador pCompile f mscorjit! Compilador fgMorph

mscorjit! Compilador pCompile d mscorjit! Compilador pCompile

mscorjit! jitNativeCode b mscorjit! Compilador pCompile

mscorjit! CILJit pileMétodo d mscorjit! jitNativeCode

x EED FF

Sistema de serialización Xml TempAssembly InvokeReader(Sistema de serialización Xml XmlMapping Sistema de Xml XmlReader Sistema de serialización Xml (Sistema de serialización Xml XmlMapping Sistema de Xml XmlReader Sistema de serialización Xml XmlDeserializationEvents Cadena del sistema)

Serialización Xml del sistema XmlReader Serialización Xml del sistema XmlDeserializationEvents Cadena del sistema

ing)

Sistema Xml Serialización XmlSerializer Deserialize (System Xml XmlReader System String) System Xml Serialization XmlSerializer Deserialize (System System IO Stream) System Xml Serialization XmlSerializer Deserialize (System Xml XmlReader System String)

Microsoft Provisioning Sdk Deserialize(System IO Stream)

Microsoft Provisioning WebServices ServiceBase Enviar[[System __Canon mscorlib] [System __Canon mscorlib]](System __Canon System String System String Boolean) Microsoft Provisioning Sdk Xml Serialización ProvisioningObjectFactory Convertir [[Sistema __Canon mscorlib] [Sistema __Canon mscorlib]] (Sistema __Canon)

Microsoft Provisioning WebServices HostedActiveDirectory Service CreateOrganization (Microsoft Provisioning WebServices HostedActiveDirectory CreateOrganizationRequest booleano)

x E BE B

x A E E

Protocolos de servicios web del sistema Invocación LogicalMethodInfo(Objeto del sistema Objeto del sistema[])

Protocolos de servicios web del sistema Invocación WebServiceHandler() Protocolos de servicios web del sistema Invocación LogicalMethodInfo( Objeto del sistema Objeto del sistema

t[])

x F FC

Subprocesos del sistema _TimerCallback TimerCallback_Context (objeto del sistema)

Ejecución de subprocesos del sistema ExecutionContext (objeto del sistema ContextCallback de subprocesos del sistema ExecutionContext)

motor web! HashtableIUnknown AddCallback un

motor web! HttpCompletion ProcessRequestInManagedCode un

motor web! HttpCompletion ProcessRequestInManagedCode un

motor web! HttpCompletion ProcessCompletion y motor web! HttpCompletion ProcessRequestInManagedCode

webengine! CorThreadPoolWorkitemCallback

x F

x F BC

kernel ! BaseThreadStart

Viendo esto, es básicamente lo mismo, creo que es un problema de código interno ¿Qué dices? Comencemos desde el principio. Hay un error de diseño en Serialización XML del sistema. Usamos reflector para ver el código de construcción de )

  {

Bloqueo (caché)

.

  {

  este tempAssembly = cache[tipo de espacio de nombre predeterminado]

if (este tempAssembly == null)

{

XmlSerializerImplementation implementación

Ensamblaje ensamblaje = TempAssembly LoadGeneratedAssembly (escriba defaultNamespace fuera de implementación)

if (assembly == null)

{

esta asignación = nuevo XmlReflectionImporter(defaultNamespace) ImportTypeMapping(tipo nulo defaultNamespace)

tipo predeterminado

ltNamespace)

}

else

{

esta asignación = XmlReflectionImporter GetTopLevelMapping(tipo defaultNamespace)

esta tempAssembly = new TempAssembly(new >

  }

Para acelerar la velocidad de ejecución, xmlserializer tiene un caché. Quizás tengamos N tipos más en el código, por lo que cada tipo tiene un ensamblado aquí. y el ensamblado se coloca en el caché. De esta manera, no hay problema, pero si hay miles o decenas de miles de tipos, entonces habrá decenas de miles de ensamblados temporales. Estos ensamblados son muy pequeños, tal vez solo un byte, tal vez. un byte, pero tenga en cuenta que cuando se asigna memoria, se asigna en bloques. Si cada bloque tiene al menos un tamaño k, incluso si solo asignamos un byte de memoria, aún necesitamos solicitar una página de k. Si tenemos muchísimos bloques pequeños, después de reducir N veces, encontrará que la memoria está en todas partes. Estos agujeros se suman a un agujero grande, pero otros no pueden usarlo porque hay k. la memoria debe estar en bloques continuos

Entonces, cuando descubrimos que w wp exe tenía solo 100 megabits, informó OOM. Esta es la razón lishixinzhi /Article/program/net/201311/12615

.