Quanta memoria utilizza un object C # /. NET?

Sto sviluppando un’applicazione che attualmente ha centinaia di oggetti creati.

È ansible determinare (o approssimare) la memoria allocata da un object (istanza di class)?

Puoi usare un profiler di memoria come

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

o

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

Un modo approssimativo potrebbe essere questo nel caso in cui vuoi sapere che cosa sta accadendo con un object particolare

// 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); 

materiale di processo ampio potrebbe essere ottenuto forse in questo modo

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

spero che questo ti aiuti 😉

Il profiler della memoria ANTS ti dirà esattamente quanto è allocato per ogni object / metodo / ecc.

Ecco un post correlato in cui abbiamo discusso la determinazione della dimensione dei tipi di riferimento.

Puoi anche usare WinDbg e SOS o SOSEX (come SOS con molti più comandi e alcuni già migliorati) estensioni WinDbg. Il comando che useresti per analizzare un object in un particolare indirizzo di memoria è! Objsize

Un elemento MOLTO importante da ricordare è che! Objsize fornisce solo la dimensione della class stessa e NON include necessariamente la dimensione degli oggetti aggregati contenuti nella class – Non ho idea del motivo per cui non lo fa perché è abbastanza frustrante e fuorviante, a volte.

Ho creato 2 Feature Suggestions sul sito Web Connect che richiedono questa possibilità di essere inclusi in VisualStudio. Si prega di votare per gli elementi di voi vorrebbero vederli aggiunti pure!

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

EDIT: Sto aggiungendo il seguente per chiarire alcune informazioni dalla risposta fornita da Charles Bretana:

  1. l’OP ha chiesto informazioni sulla dimensione di un ‘object’ non di una ‘class’. Un object è un’istanza di una class. Forse è questo che intendevi?
  2. La memoria allocata per un object non include il codice JITted. Il codice JIT vive nel proprio “JIT Code Heap”.
  3. La JIT compila il codice solo su una base metodo per metodo, non a livello di class. Quindi, se un metodo non viene mai chiamato per una class, non viene mai compilato JIT e quindi non ha mai memoria allocata per questo sull’heap del codice JIT.

Per inciso, ci sono circa 8 diversi heap che il CLR usa:

  1. Loader Heap: contiene le strutture CLR e il sistema di tipi
  2. Heap ad alta frequenza: statica, MethodTables, FieldDescs, mappa dell’interfaccia
  3. Heap a bassa frequenza: EEClass, ClassLoader e tabelle di ricerca
  4. Stub Heap: stub per CAS, wrapper COM, P / Invoke
  5. Large Object Heap: allocazioni di memoria che richiedono più di 85k byte
  6. GC Heap: memoria heap allocata dall’utente all’app
  7. HIT Code Heap: memoria allocata da mscoreee (Execution Engine) e il compilatore JIT per il codice gestito
  8. Process / Base Heap: allocazioni interop / unmanaged, memoria nativa, ecc

HTH

Per avere un’idea generale dell’allocazione di memoria nell’applicazione, utilizzare il seguente comando sos in WinDbg

 !dumpheap -stat 

Si noti che! Dumpheap fornisce solo i byte del tipo di object stesso e non include i byte di altri tipi di oggetti a cui potrebbe fare riferimento.

Se vuoi vedere il totale dei byte in attesa (sum di tutti i byte di tutti gli oggetti referenziati dal tuo object) di un tipo specifico di object, usa un profiler di memoria come dot Trace – http://www.jetbrains.com/profiler/

Ogni “class” richiede abbastanza memoria per contenere tutto il codice jit-compilato per tutti i suoi membri che sono stati chiamati dal runtime, (anche se se non si chiama un metodo per un po ‘di tempo, il CLR può rilasciare quella memoria e ripetilo di nuovo se lo chiami di nuovo … più memoria sufficiente per contenere tutte le variabili statiche dichiarate nella class … ma questa memoria viene allocata solo una volta per class, indipendentemente da quante istanze della class tu crei.

Per ogni istanza della class che si crea, (e non è stata raccolta Garbage) è ansible approssimare l’impronta di memoria sumndo l’utilizzo della memoria per ogni variabile dichiarata basata sull’istanza … (campo)

le variabili di riferimento (riferimenti ad altri oggetti) richiedono 4 o 8 byte (OS a 32/64 bit?) int16, Int32, Int64 prendono 2,4 o 8 byte, rispettivamente …

la variabile stringa richiede spazio aggiuntivo per alcuni metadati, (più la dimensione del puntatore dell’indirizzo)

Inoltre, ogni variabile di riferimento in un object può anche essere considerata per “indirettamente” includere la memoria occupata nell’heap dall’object a cui punta, anche se probabilmente vorrai contare quella memoria come appartenente a quell’object non la variabile che fa riferimento a …

ecc. ecc.

Se puoi – Serializzalo!

 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 

C’è la domanda accademica di Qual è la dimensione di un object in fase di runtime? E questo è interessante, ma può essere correttamente risposto solo da un profiler che è collegato al processo in esecuzione. Ho passato un po ‘di tempo a guardarlo e ho scoperto che non esiste un metodo generico accurato e abbastanza veloce da poterlo utilizzare in un sistema di produzione. Casi semplici come matrici di tipi numerici hanno risposte facili, ma al di là di questo la risposta migliore sarebbe Non preoccuparti di cercare di risolverlo. Perché vuoi sapere questo? Sono disponibili altre informazioni che potrebbero servire allo stesso scopo?

Nel mio caso ho finito col voler rispondere a questa domanda perché avevo vari dati che erano utili, ma potrebbero essere scartati per liberare RAM per servizi più critici. I ragazzi dei poster qui sono un Undo Stack e un Cache .

Alla fine ho concluso che il modo giusto per gestire la dimensione dello stack di annullamento e della cache era di interrogare la quantità di memoria disponibile (è un processo a 64 bit quindi è sicuro presumere che sia tutto disponibile) e quindi consentire più elementi da aggiungere se c’è un buffer sufficientemente grande di RAM e richiedono elementi da rimuovere se la RAM sta per esaurirsi.