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



title tag definition (8)

Es gibt die akademische Frage: Wie 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 mich eine ganze Weile damit beschäftigt, dies zu untersuchen und festgestellt, dass es keine generische Methode gibt, die genau und schnell genug ist, dass Sie sie jemals in einem Produktionssystem verwenden möchten. Einfache Fälle wie Arrays numerischer Typen haben einfache Antworten, aber darüber hinaus wäre die beste Antwort: Versuchen Sie nicht, es auszuarbeiten. 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 ich verschiedene Daten hatte, die nützlich waren, aber entsorgt werden konnten, um RAM für kritischere Dienste freizumachen. Die Posterjungen hier sind ein Undo Stack und ein Cache .

Schließlich kam ich zu dem Schluss, dass der richtige Weg zur Verwaltung der Größe des Undo-Stacks und des Caches die Abfrage des verfügbaren Speichers ist (es ist ein 64-Bit-Prozess, so dass davon ausgegangen werden kann, dass alles verfügbar ist) und dann weitere Elemente zulassen hinzugefügt werden, wenn ein ausreichend großer RAM-Puffer vorhanden ist und Elemente erforderlich sind, die entfernt werden müssen, wenn der RAM-Speicher knapp wird.

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

Ist es möglich, den von einem Objekt (Klasseninstanz) zugewiesenen Speicher zu bestimmen (oder zu approximieren)?


Answer #1

Jede "Klasse" benötigt genügend Speicher, um ihren gesamten jit-kompilierten Code für alle Mitglieder aufzunehmen, die von der Laufzeit aufgerufen wurden. (Wenn Sie eine Methode längere Zeit nicht aufrufen, kann die CLR diesen Speicher freigeben und re-jit es erneut, wenn Sie es erneut aufrufen ... plus genügend Speicher für alle statischen Variablen in der Klasse deklariert ... aber dieser Speicher wird nur einmal pro Klasse zugewiesen, egal wie viele Instanzen der Klasse, die Sie erstellen.

Für jede Instanz der Klasse, die Sie erstellen (und wurde nicht von Garbage Collection erfasst), können Sie den Speicherbedarf durch Addieren der Speicherauslastung für jede Instanz deklarierte Variable annähern ... (Feld)

Referenzvariablen (refs zu anderen Objekten) nehmen 4 oder 8 Bytes (32/64 bit OS?) int16, Int32, Int64 nehmen 2,4 bzw. 8 Bytes ...

Die Zeichenfolgevariable benötigt zusätzlichen Speicher für einige Metadatenelemente (zuzüglich der Größe des Adresszeigers)

Darüber hinaus könnte jede Referenzvariable in einem Objekt auch als "indirekt" den Speicher in Betracht ziehen, den das Objekt, auf das es zeigt, auf den Heapspeicher nimmt, obwohl Sie diesen Speicher wahrscheinlich als zu diesem Objekt gehörend zählen und nicht als die Variable verweist darauf ...

usw. usw.


Answer #2

Der ANTS Speicher Profiler wird Ihnen genau sagen, wie viel für jedes Objekt / Methode / etc zugewiesen ist.


Answer #3

Sie können auch WinDbg und entweder SOS oder SOSEX (wie SOS mit vielen weiteren Befehlen und einige bereits bestehende) WinDbg-Erweiterungen verwenden. Der Befehl, den Sie verwenden würden, um ein Objekt an einer bestimmten Speicheradresse zu analysieren, ist! Objsize

Ein sehr wichtiger Punkt, der zu beachten ist, dass! Objsize nur die Größe der Klasse selbst angibt und NICHT unbedingt die Größe der in der Klasse enthaltenen Aggregatobjekte enthält - ich habe keine Ahnung, warum es das nicht so macht, wie es ist manchmal frustrierend und irreführend.

Ich habe auf der Connect-Website 2 Feature-Vorschläge erstellt, in denen nach einer Integration dieser Fähigkeit in VisualStudio gefragt wird. Bitte stimme für die Gegenstände von dir ab, die sie ebenfalls sehen 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 klären:

  1. Das OP fragte nach der Größe eines "Objekts" und nicht nach einer "Klasse". Ein Objekt ist eine Instanz einer Klasse. Vielleicht hast du das gemeint?
  2. Der für ein Objekt reservierte Speicher enthält den JITted-Code nicht. Der JIT-Code lebt in seinem eigenen 'JIT Code Heap'.
  3. Der JIT kompiliert den Code nur methodisch nach Methoden - nicht auf Klassenebene. Wenn also eine Methode niemals für eine Klasse aufgerufen wird, wird sie niemals JIT-kompiliert und daher ist ihr niemals Speicher auf dem JIT-Code-Heap zugewiesen.

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

  1. Loader Heap: enthält CLR-Strukturen und das Typsystem
  2. Hochfrequenz-Heap: Statik, MethodTables, FieldDescs, Interface-Map
  3. Niederfrequenz-Heap: EEClass-, ClassLoader- und Lookup-Tabellen
  4. Stub Heap: Stubs für CAS, COM Wrapper, P / Invoke
  5. Large Object Heap: Speicherzuordnungen, die mehr als 85 KB erfordern
  6. GC Heap: Der Benutzer hat der App den privaten Speicher zugewiesen
  7. JIT-Code-Heap: Speicher, der von mscoreee (Execution Engine) und dem JIT-Compiler für verwalteten Code zugewiesen wurde
  8. Prozess / Basis Heap: Interop / Unmanaged Allokationen, nativer Speicher, etc

HTH


Answer #4

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



Answer #7

Um einen allgemeinen Überblick über die Speicherzuordnung in Ihrer Anwendung zu erhalten, verwenden Sie den folgenden Befehl sos in WinDbg

!dumpheap -stat

Beachten Sie, dass! Dumpheap nur die Bytes des Objekttyps selbst angibt und die Bytes anderer Objekttypen, auf die verwiesen wird, nicht enthält.

Wenn Sie die Gesamtzahl der Bytes (Summe aller Bytes aller von Ihrem Objekt referenzierten Objekte) eines bestimmten Objekttyps anzeigen möchten, verwenden Sie einen Speicherprofiler wie den Punkt Trace - http://www.jetbrains.com/profiler/





profiling