¿Cuánta memoria usa un objeto C # /. NET?

Estoy desarrollando una aplicación que actualmente tiene cientos de objetos creados.

¿Es posible determinar (o aproximar) la memoria asignada por un objeto (instancia de clase)?

Podría usar un generador de perfiles de memoria como

.NET Memory Profiler ( http://memprofiler.com/ )

o

CLR Profiler (gratuito) ( http://clrprofiler.codeplex.com/ )

Una manera grosera podría ser esta en caso de que quieras saber qué está pasando con un objeto en particular

// Measure starting point memory use GC_MemoryStart = System.GC.GetTotalMemory(true); // Allocate a new byte array of 20000 elements (about 20000 bytes) MyByteArray = new byte[20000]; // Obtain measurements after creating the new byte[] GC_MemoryEnd = System.GC.GetTotalMemory(true); // Ensure that the Array stays in memory and doesn't get optimized away GC.KeepAlive(MyByteArray); 

procesar todo el material se podría obtener tal como esto

 long Process_MemoryStart = 0; Process MyProcess = System.Diagnostics.Process.GetCurrentProcess(); Process_MemoryStart = MyProcess.PrivateMemorySize64; 

espero que esto ayude 😉

El generador de perfiles de memoria ANTS le dirá exactamente cuánto se asigna para cada objeto / método / etc.

Aquí hay una publicación relacionada donde discutimos la determinación del tamaño de los tipos de referencia.

También puede usar WinDbg y SOS o SOSEX (como SOS con muchos más comandos y algunos ya existentes mejorados) extensiones de WinDbg. El comando que usaría para analizar un objeto en una dirección de memoria particular es! Objsize

Un elemento MUY importante para recordar es que! Objsize solo te da el tamaño de la clase en sí y NO incluye necesariamente el tamaño de los objetos agregados contenidos dentro de la clase. No tengo idea de por qué no hace esto, ya que es bastante frustrante y engañoso a veces.

Creé 2 Sugerencias de funciones en el sitio web de Connect que solicitan que se incluya esta capacidad en VisualStudio. ¡Vote por los artículos que le gustaría ver agregados también!

https://connect.microsoft.com/VisualStudio/feedback/details/637373/add-feature-to-debugger-to-view-an-objects-memory-footprint-usage

https://connect.microsoft.com/VisualStudio/feedback/details/637376/add-feature-to-debugger-to-view-an-objects-rooted-references

EDITAR: Estoy agregando lo siguiente para aclarar alguna información de la respuesta proporcionada por Charles Bretana:

  1. OP preguntó sobre el tamaño de un “objeto” y no una “clase”. Un objeto es una instancia de una clase. Quizás esto es lo que querías decir?
  2. La memoria asignada para un objeto no incluye el código JITted. El código JIT vive en su propio ‘Hep Code Heap’.
  3. El JIT solo comstack código método por método, no a nivel de clase. Entonces, si nunca se llama a un método para una clase, nunca se comstack JIT y, por lo tanto, nunca tiene memoria asignada para él en el Heap de Código JIT.

Como un lado, hay aproximadamente 8 montones diferentes que utiliza el CLR:

  1. Loader Heap: contiene estructuras CLR y el sistema de tipos
  2. Heap de alta frecuencia: statics, MethodTables, FieldDescs, mapa de interfaz
  3. Montón de baja frecuencia: EEClass, ClassLoader y tablas de búsqueda
  4. Stub Heap: stubs para CAS, envolturas COM, P / Invoke
  5. Montón de objetos grandes: asignaciones de memoria que requieren más de 85k bytes
  6. GC Heap: el usuario asigna memoria de montón privada a la aplicación
  7. Heap de código JIT: memoria asignada por mscoreee (motor de ejecución) y el comstackdor JIT para código administrado
  8. Heap de base / proceso: asignaciones interoperativas / no gestionadas, memoria nativa, etc.

HTH

Para tener un sentido general de la asignación de memoria en su aplicación, use el siguiente comando sos en WinDbg

 !dumpheap -stat 

Tenga en cuenta que! Dumpheap solo le proporciona los bytes del tipo de objeto en sí, y no incluye los bytes de ningún otro tipo de objeto al que pueda hacer referencia.

Si desea ver el total de bytes retenidos (sumr todos los bytes de todos los objetos a los que hace referencia su objeto) de un tipo de objeto específico, utilice un perfilador de memoria como dot Trace – http://www.jetbrains.com/profiler/

Cada “clase” requiere suficiente memoria para mantener todo su código comstackdo de jit para todos sus miembros que han sido llamados por el tiempo de ejecución (aunque si no llama a un método durante bastante tiempo, el CLR puede liberar esa memoria y Vuelva a activarlo si lo vuelve a llamar … más memoria suficiente para mantener todas las variables estáticas declaradas en la clase … pero esta memoria se asigna solo una vez por clase, sin importar cuántas instancias de la clase cree.

Para cada instancia de la clase que usted crea, (y no se ha recogido basura), puede aproximar la huella de memoria sumndo el uso de memoria por cada variable declarada basada en instancia … (campo)

las variables de referencia (refs a otros objetos) toman 4 u 8 bytes (32/64 bit OS?) int16, Int32, Int64 toman 2,4 u 8 bytes, respectivamente …

La variable de cadena toma almacenamiento adicional para algunos elementos de metadatos (más el tamaño del puntero de dirección)

Además, también se puede considerar que cada variable de referencia en un objeto incluye “indirectamente” la memoria tomada en el montón por el objeto al que apunta, aunque es probable que desee contar esa memoria como perteneciente a ese objeto, no como la variable que lo hace referencia …

etcétera etcétera.

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 

Existe la pregunta académica de ¿Cuál es el tamaño de un objeto en tiempo de ejecución? Y eso es interesante, pero solo puede ser respondido adecuadamente por un generador de perfiles adjunto al proceso en ejecución. Pasé bastante tiempo mirando esto recientemente y determiné que no existe un método genérico que sea lo suficientemente preciso y rápido como para querer utilizarlo en un sistema de producción. Casos simples como arreglos de tipos numéricos tienen respuestas fáciles, pero más allá de esto, la mejor respuesta sería No se moleste en tratar de resolverlo. ¿Por qué quieres saber esto? ¿Hay otra información disponible que podría servir para el mismo propósito?

En mi caso, terminé queriendo responder a esta pregunta porque tenía varios datos que eran útiles, pero podría descartarse para liberar RAM para servicios más críticos. Los chicos del cartel aquí son una stack de deshacer y un caché .

Finalmente llegué a la conclusión de que la forma correcta de gestionar el tamaño de la stack de deshacer y el caché era consultar la cantidad de memoria disponible (es un proceso de 64 bits, por lo que es seguro suponer que está disponible) y luego permitir más elementos que se agregará si hay un búfer suficientemente grande de RAM y requiere que se eliminen elementos si la RAM se está agotando.