it-swarm.com.de

Wie viel Speicher belegt ein C # /. NET-Objekt?

Ich entwickle eine Anwendung, die derzeit Hunderte von Objekten erstellt hat. 

Kann man den von einem Objekt zugewiesenen Speicher (Klasseninstanz) ermitteln (oder annähern)? 

50
FerranB

Sie könnten einen Memory-Profiler verwenden

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

oder

CLR-Profiler (kostenlos) ( http://clrprofiler.codeplex.com/ )

39
Rauhotz

Ein grober Weg könnte der Fall sein, wenn Sie wissen möchten, was mit einem bestimmten Objekt passiert

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

prozessweites Zeug könnte vielleicht so erhalten werden

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

hoffe das hilft ;)

37
varun

Der ANTS Speicherprofiler sagt Ihnen genau, wie viel für jedes Objekt/jede Methode/etc vergeben wird.

11
George Stocker

Hier ist ein verwandter Beitrag wo wir die Größe der Referenztypen bestimmt haben.

10
John Sheehan

Sie können auch WinDbg und entweder SOS oder SOSEX (wie SOS mit vielen weiteren Befehlen und einigen vorhandenen verbesserten WinDbg-Erweiterungen) verwenden. Der Befehl, den Sie zur Analyse eines Objekts an einer bestimmten Speicheradresse verwenden würden, ist! Objsize

Ein sehr wichtiges Element, das Sie beachten sollten, ist, dass! Objsize nur die Größe der Klasse selbst angibt und NICHT unbedingt die Größe der in der Klasse enthaltenen Aggregatobjekte einschließt. Ich habe keine Ahnung, warum dies nicht der Fall ist manchmal frustrierend und irreführend.

Ich habe auf der Connect-Website 2 Funktionsvorschläge erstellt, in denen Sie gefragt werden, ob diese Funktion in VisualStudio enthalten sein kann. Bitte stimmen Sie für die Artikel von Ihnen, die ebenfalls hinzugefügt werden möchten!

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: Ich füge Folgendes hinzu, um einige Informationen aus der Antwort von Charles Bretana zu erläutern:

  1. das OP fragte nach der Größe eines 'Objekts', nicht einer 'Klasse'. Ein Objekt ist eine Instanz einer Klasse. Vielleicht haben Sie das gemeint?
  2. Der für ein Objekt zugewiesene Speicher enthält nicht den JITted-Code. Der JIT-Code lebt in einem eigenen 'JIT-Code-Heap'. 
  3. Die JIT kompiliert Code nur methodenweise - nicht auf Klassenebene. Wenn also eine Methode nie für eine Klasse aufgerufen wird, wird sie niemals JIT kompiliert und hat daher niemals Speicherplatz auf dem JIT-Code-Heap zugewiesen.

Daneben gibt es ungefähr 8 verschiedene Heaps, die die CLR verwendet:

  1. Loader Heap: enthält CLR-Strukturen und das Typsystem
  2. High Frequency Heap: Statik, Methodentabellen, FieldDescs, Schnittstellenkarte
  3. Niederfrequenzhaufen: EEClass, ClassLoader und Nachschlagetabellen
  4. Stub Heap: Stubs für CAS, COM-Wrapper, P/Invoke
  5. Large Object Heap: Speicherzuordnungen, für die mehr als 85 KB erforderlich sind
  6. GC-Heap: Der Benutzer hat der App privaten Heap-Speicher zugewiesen
  7. JIT-Code-Heap: Speicher, der von mscoreee (Execution Engine) und dem JIT-Compiler für verwalteten Code zugewiesen wird 
  8. Process/Base Heap: Interop/nicht verwaltete Zuweisungen, nativer Speicher usw

HTH

7
Dave Black

Um ein allgemeines Verständnis für die Speicherzuordnung in Ihrer Anwendung zu erhalten, verwenden Sie den folgenden Befehl sos in WinDbg

!dumpheap -stat

Beachten Sie, dass! Dumpheap Ihnen nur die Bytes des Objekttyps selbst gibt und nicht die Bytes anderer Objekttypen enthält, auf die er verweist.

Wenn Sie die insgesamt gehaltenen Bytes (Summe aller Bytes aller Objekte, auf die Ihr Objekt verweist) eines bestimmten Objekttyps anzeigen möchten, verwenden Sie einen Speicherprofiler wie dot Trace - http://www.jetbrains.com/profiler/

6
Sean

Für jede "Klasse" ist genügend Speicherplatz erforderlich, um den gesamten mit Jit kompilierten Code für alle von der Laufzeitumgebung aufgerufenen Member zu speichern. (Wenn Sie jedoch eine Methode längere Zeit nicht aufrufen, kann die CLR diesen Speicher freigeben und Wenn Sie es erneut aufrufen, jit es erneut ... und genügend Speicherplatz, um alle in der Klasse deklarierten statischen Variablen zu speichern. Dieser Speicher wird jedoch nur einmal pro Klasse zugewiesen, unabhängig davon, wie viele Instanzen der Klasse Sie erstellen. 

Für jede Instanz der Klasse, die Sie erstellen (und die noch nicht mit Garbage gesammelt wurde), können Sie den Speicherbedarf abschätzen, indem Sie die Speicherbelegung für jede instanzbasierte deklarierte Variable ... (Feld) addieren. 

referenzvariablen (Verweise auf andere Objekte) benötigen 4 oder 8 Bytes (32/64 Bit OS?) int16, Int32, Int64 benötigen 2,4 bzw. 8 Bytes ... 

zeichenfolgenvariable benötigt zusätzlichen Speicherplatz für einige Metadatenelemente (plus die Größe des Adresszeigers) 

Außerdem kann jede Referenzvariable in einem Objekt als "indirekt" angesehen werden, wenn der Speicher, den das Objekt auf das Heap belegt, belegt ist, obwohl Sie diesen Speicher wahrscheinlich als zu diesem Objekt gehörend bezeichnen möchten und nicht als Variable verweist darauf ... 

etc. etc.

6
Charles Bretana

Wenn Sie können - Serialisieren Sie es!

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
5
serhio

Es gibt die wissenschaftliche Frage nachWie groß ist ein Objekt zur Laufzeit?Und das ist interessant, aber es kann nur von einem Profiler richtig beantwortet werden, der an den laufenden Prozess angehängt ist. Ich habe mir vor kurzem eine ganze Weile damit befasst und festgestellt, dass es keine generische Methode gibt, die genau und schnell genug ist, um sie jemals in einem Produktionssystem verwenden zu können. Einfache Fälle wie Arrays numerischer Typen haben einfache Antworten, aber darüber hinaus wäre die beste Antwort:Versuchen Sie nicht, es herauszufinden. Warum willst du das wissen? Gibt es andere Informationen, die dem gleichen Zweck dienen könnten?

In meinem Fall wollte ich diese Frage beantworten, weil mir verschiedene Daten zur Verfügung standen, die nützlich waren, aber verworfen werden konnten, um RAM für kritischere Dienste freizugeben. Die Posterboys hier sind ein Undo Stack und ein Cache .

Schließlich kam ich zu dem Schluss, dass der richtige Weg zum Verwalten der Größe des Rückgängig-Stapels und des Cache-Speichers darin bestand, den verfügbaren Speicher abzufragen (dies ist ein 64-Bit-Prozess, sodass davon auszugehen ist, dass alles verfügbar ist) und dann mehr Elemente zugelassen werden Wird hinzugefügt, wenn ein ausreichend großer Puffer von RAM vorhanden ist und Elemente entfernt werden müssen, wenn RAM schwach wird.

1
briantyler