2009-03-03 28 views
154

Ho bisogno di sapere quanti byte il mio oggetto consuma in memoria (in C#). per esempio quanto il mio Hashtable o SortedList o List<String>.Come ottenere la dimensione dell'oggetto in memoria?

+0

E http://stackoverflow.com/questions/207592/getting-the-size-of-a-field-in-bytes-with -c –

+0

Io secondo, chiudendo questo e cerco risposte già date. Entrambi suggeriti da Jon sono validi. –

+0

terzo, ma offensivo? – annakata

risposta

85

non credo che si può ottenere direttamente, ma ci sono alcuni modi per trovare indirettamente.

Un modo è utilizzare il metodo GC.GetTotalMemory per misurare la quantità di memoria utilizzata prima e dopo aver creato l'oggetto. Questo non sarà perfetto, ma finché controlli il resto dell'applicazione potresti ottenere le informazioni che ti interessano.

A parte questo puoi usare un profiler per ottenere le informazioni oppure puoi usare il profiling api per ottenere le informazioni nel codice. Ma non sarà facile da usare, penso.

Vedere Find out how much memory is being used by an object in C#? per una domanda simile.

+1

+1 è stato abbastanza buono per me! –

+5

Mentre la "vera" risposta potrebbe essere "non si può fare", la risposta migliore è quella che ti offre un'alternativa possibile. –

+0

Questo ha funzionato bene per me. Nel mio caso stavo lavorando con un oggetto molto complesso che non poteva essere serializzato facilmente, quindi i top an erano fuori questione. Ho usato questo metodo con un ciclo for per ottenere una media approssimativa in ogni punto. Mi ha aiutato a vedere la differenza tra quando questa entità non esisteva e poi ha funzionato. Delta == dimensione approssimativa dell'entità. – user2326106

1

In modalità debug

carico SOS

ed eseguire il comando dumpheap.

+2

sembra qualcosa da windbg, e potrebbe essere davvero utile. Puoi elaborare come farlo in Visual Studio? –

138
long size = 0; 
object o = new object(); 
using (Stream s = new MemoryStream()) { 
    BinaryFormatter formatter = new BinaryFormatter(); 
    formatter.Serialize(s, o); 
    size = s.Length; 
} 
+25

+1 "potrebbe non essere preciso ma è abbastanza vicino per me" – Achilles

+84

Questo metterà molto di più. Aggiunge il nome e la versione della DLL, ... ** questo non è un modo per calcolare la dimensione dell'oggetto. ** – Aliostad

+32

Non vedo alcuna risposta nel tuo blob di testo. –

14

Il seguente frammento di codice dovrebbe restituire la dimensione in byte di qualsiasi oggetto passato ad esso, purché possa essere serializzata. L'ho ottenuto da un collega di Quixant per risolvere un problema di scrittura su SRAM su una piattaforma di gioco. Spero che aiuti. Credito e grazie a Carlo Vittuci.

/// <summary> 
/// Calculates the lenght in bytes of an object 
/// and returns the size 
/// </summary> 
/// <param name="TestObject"></param> 
/// <returns></returns> 
private int GetObjectSize(object TestObject) 
{ 
    BinaryFormatter bf = new BinaryFormatter(); 
    MemoryStream ms = new MemoryStream(); 
    byte[] Array; 
    bf.Serialize(ms, TestObject); 
    Array = ms.ToArray(); 
    return Array.Length; 
} 
+0

Non ha funzionato per me. Non avevo la classe dell'oggetto definita come serializzabile e lanciava un messaggio "Non contrassegnato come errore serializzabile" – dreamerkumar

+2

Ciao @Kevin Hirst, ho provato con questo che ha analizzato il mio set di dati per ottenere la dimensione in byte. Mi restituisce l'eccezione di memoria esaurita. Scoprirò che la dimensione massima dei byte è 2 GB? Hai qualche idea su come gestirlo? – Worgon

+0

@ Worgon, hai davvero bisogno di sapere quanto è grande il set di dati tranne che per scopi di indagine? Preferirei pensare a un livello, per eliminare una tale necessità. Se insisti, potresti pensare a una particolare dimensione di Datarow o usare l'approccio di "GC.GetTotalMemory" sopra menzionato. –

22

OK, questa domanda è stato risposto e risposta accettata, ma qualcuno mi ha chiesto di mettere la mia risposta quindi non ci si va.

Prima di tutto, non è possibile dirlo con certezza. Si tratta di un dettaglio di implementazione interno e non documentato. Tuttavia, in base agli oggetti inclusi nell'altro oggetto. Ora, come calcoliamo il requisito di memoria per i nostri oggetti memorizzati nella cache?

avevo toccato in precedenza questo argomento in questo article:

Ora, come si fa a calcolare il requisito di memoria per i nostri cache oggetti?Bene, come molti di voi saprebbero, Int32 e float sono quattro byte , double e DateTime 8 byte, char in realtà due byte (non un byte) e così via. La stringa è un po 'più complessa, 2 * (n + 1), dove n è la lunghezza della stringa. Per gli oggetti, dipenderà dai membri : basta sommare il requisito di memoria di tutti i suoi membri, ricordando tutti i riferimenti oggetto sono semplicemente 4 byte puntatori su una casella 32 bit. Ora, questo in realtà non è del tutto vero, non ci siamo presi cura dello del sovraccarico di ogni oggetto nell'heap. Non sono sicuro che sia necessario il preoccuparsi di ciò, ma suppongo che se si utilizzeranno lotti di piccoli oggetti, si dovrebbe prendere in considerazione l'overhead in . Ogni oggetto heap costa tanto quanto i suoi tipi primitivi, più quattro byte per i riferimenti oggetto (su una macchina a 32 bit, sebbene BizTalk esegua anche 32 bit su macchine a 64 bit), più 4 byte per il puntatore dell'oggetto tipo e Penso 4 byte per l'indice del blocco di sincronizzazione. Perché è questo overhead aggiuntivo importante? Bene, immaginiamo di avere una classe con due membri di Int32; in questo caso, il requisito di memoria è 16 byte e non 8.

+2

penso che questo dovrebbe essere contrassegnato come risposta. che dice usa il tuo cervello invece del computer! ;) –

+0

Questo non risponde alla domanda dell'OP, come dovremmo misurare la dimensione di un HashSet contro un elenco? –

Problemi correlati