collector - Descubre el tamaño de un objeto.net
garbage collector c# (7)
Estoy tratando de averiguar cuánta memoria toman mis objetos para ver cuántos de ellos terminan en el Heap de Objetos Grandes (que es más de 85,000 bytes).
¿Es tan simple como agregar 4 para un int, 8 para un largo, 4 (u 8 si tiene 64 bits) para cualquier tipo de referencia, etc. para cada objeto, o hay gastos generales para métodos, propiedades, etc.
A menos que sea un gran tipo de valor o tipo de instancia (es decir, muchos miles de campos), los únicos tipos de los que debe preocuparse son las grandes matrices o cadenas. Por supuesto, para determinar el tamaño de una matriz, necesita saber el tamaño del elemento.
.NET (actualmente) alinea los tipos casi de la misma manera que los compiladores nativos alinean los tipos. Los tipos fundamentales tienen alineamientos naturales que generalmente son la potencia integral redondeada de los dos más cercanos a su tamaño:
Single, Int32, UInt32 - 4
IntPtr, UIntPtr, pointers, references - 4 on 32-bit, 8 on 64-bit
Double, Int64, UInt64 - 8
Char, Int16, UInt16 - 2
Byte, SByte - 1
Al ensamblar un tipo, el compilador se asegurará de que todos los campos de cualquier tipo tengan su desplazamiento de inicio dentro de la instancia alineada a un límite que coincida con ese tipo, suponiendo que no se esté utilizando el diseño explícito.
Los propios tipos definidos por el usuario tienen una alineación, que se calcula como la alineación más alta de cualquiera de sus tipos de campo. El tamaño del tipo se amplía si es necesario para que el tamaño del tipo también esté alineado.
Pero, por supuesto, todos los tipos de referencia siguen teniendo tamaño y alineación IntPtr.Size, por lo que el tamaño del tipo de referencia no afectará a las matrices de ese tipo.
Tenga en cuenta que el CLR puede elegir, a su discreción, los tipos de diseño de forma diferente a la descrita anteriormente, tal vez para aumentar la localidad de caché o reducir el relleno requerido por la alineación.
Como estimación (en 2017) puede depurar en su aplicación, establecer un punto de interrupción antes de la puesta en funcionamiento del diccionario, tomar una "Instantánea de uso de memoria" (pestaña: Uso de memoria en Herramientas de diagnóstico), llenar el diccionario y obtener otra instantánea, no exacto poner un buen gestimate.
El método de Gomes simplificado:
vaya a Visual Studio (2010) Propiedades del proyecto -> pestaña Depurar -> Habilitar la depuración del código no administrado.
Establezca el punto de interrupción en su código, comience a depurar (F5).
Abrir Depuración -> Windows -> Ventana Inmediata.
entrar .load sos
ingrese (reemplace myObject con el nombre de su objeto)
? String.Format ("{0: x}", Integer.Parse (System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject (System.Runtime.InteropServices.GCHandle.Alloc (myObject) .GetHandleValue ()). ToString ()) - 4 )
6. Usa el resultado como parámetro de! ObjSize
ver: SOS.DLL, dirección del objeto y depurador de Visual Studio Introducción
Ejemplo (estamos buscando un objeto llamado tbl
):
.load sos
extension C:/Windows/Microsoft.NET/Framework/v4.0.30319/sos.dll loaded
? string.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(tbl).GetHandleValue()).ToString())-4)
"27ccb18"
!ObjSize 27ccb18
PDB symbol for clr.dll not loaded
sizeof(027ccb18) = 154504 ( 0x25b88) bytes (System.Data.DataTable)
Está ingresando en un área de depuración .NET avanzada. Comience con los libros de depuración John Robins .
Use WinDBG con Sos.dll (parte de la distribución .NET) y extensiones Sosex.dll . Con estas herramientas, realmente puede ver lo que sucede cuando su aplicación se está ejecutando. Encontrarás respuestas a tus preguntas antes mencionadas.
(Otra recomendación sería instalar Shared Source CLI 2.0 , también conocido como Rotor 2, para ver qué sucede bajo el capó).
No olvide que el tamaño de un objeto real no incluye el tamaño de los objetos a los que hace referencia.
Lo único que probablemente terminará en el gran montón de objetos son las matrices y las cadenas; otros objetos tienden a ser relativamente pequeños en sí mismos. Incluso un objeto con (digamos) 10 variables de tipo de referencia (4 bytes cada una en x86) y 10 GUID (16 bytes cada una) solo ocupará unos 208 bytes (hay un poco de sobrecarga para la referencia de tipo y el bloque de sincronización).
Del mismo modo, al pensar en el tamaño de una matriz, no olvide que si el tipo de elemento es un tipo de referencia, solo el tamaño de las referencias cuenta para la matriz misma. En otras palabras, incluso si tiene una matriz con 20,000 elementos, el tamaño del objeto de matriz solo será un poco más de 80K (en x86) incluso si hace referencia a muchos más datos.
Por favor, siga estos pasos para obtener el tamaño del objeto.
1) ir a Visual Studio (2010) Propiedades del proyecto -> pestaña Depurar -> Habilitar la depuración del código no administrado.
2) vaya al menú Depuración de Visual Studio -> Opción y configuración -> Depuración -> Símbolos.
3) Habilite Microsoft Symbol Server, deje el valor predeterminado. (Los símbolos pueden comenzar la descarga)
4) Establezca el punto de interrupción en su código, comience a depurar (F5).
5) Abrir Depuración -> Windows -> Ventana Inmediata.
6) ingrese .load sos.dll (Son of Strike)
7) enter! DumpHeap -type MyClass (el objeto que desea buscar tamaño)
8) desde el exterior ubicar la dirección del objeto, es decir (00a8197c)
Dirección MT Tamaño 00a8197c 00955124 36
9) Siguiente,! ObjSize 00a8197c
10) Ahí va -> sizeof (00a8197c) = 12 (0x48) bytes (MyClass)
Si puedes: ¡serializarlo!
Dim myObjectSize As Long
Dim ms As New IO.MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(ms, myObject)
myObjectSize = ms.Position