web-dev-qa-db-fra.com

Combien de mémoire un objet C #/.NET utilise-t-il?

Je développe une application qui a actuellement des centaines d'objets créés. 

Est-il possible de déterminer (ou approximer) la mémoire allouée par un objet (instance de classe)? 

50
FerranB

Vous pouvez utiliser un profileur de mémoire comme

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

ou

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

39
Rauhotz

Une façon grossière pourrait être la suivante si vous voulez savoir ce qui se passe avec un objet particulier

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

processus large pourrait être obtenu peut-être comme ça

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

j'espère que cela t'aides ;)

37
varun

Le profileur de mémoire ANTS vous indiquera exactement le montant alloué pour chaque objet/méthode/etc.

11
George Stocker

Voici un article connexe où nous avons discuté de la détermination de la taille des types de référence.

10
John Sheehan

Vous pouvez également utiliser WinDbg et SOS ou SOSEX (comme SOS avec beaucoup plus de commandes et des commandes existantes améliorées) WinDbg extensions. La commande que vous utiliseriez pour analyser un objet à une adresse mémoire particulière est! Objsize

Un élément TRÈS important à retenir est que! Objsize ne vous donne que la taille de la classe elle-même et n'inclut pas nécessairement la taille des objets agrégés contenus dans la classe - je ne vois pas pourquoi il ne le fait pas, car il est assez frustrant et trompeur parfois.

J'ai créé 2 suggestions de fonctionnalités sur le site Web de Connect qui demandent que cette capacité soit incluse dans VisualStudio. S'il vous plaît voter pour les éléments de vous voudriez les voir ajoutés aussi bien!

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: J'ajoute ce qui suit pour clarifier certaines informations de la réponse fournie par Charles Bretana:

  1. le PO a posé des questions sur la taille d'un "objet" et non d'une "classe". Un objet est une instance d'une classe. Peut-être que c'est ce que tu voulais dire?
  2. La mémoire allouée à un objet n'inclut pas le code JITted. Le code JIT vit dans son propre "tas de code JIT". 
  3. Le JIT compile le code méthode par méthode, pas au niveau de la classe. Ainsi, si une méthode n'est jamais appelée pour une classe, elle n'est jamais compilée par JIT et, par conséquent, jamais de mémoire ne lui est allouée sur le tas de code JIT.

En passant, le CLR utilise environ 8 tas différents:

  1. Loader Heap: contient les structures CLR et le système de types
  2. Heap haute fréquence: statique, MethodTables, FieldDescs, carte d'interface
  3. Tas de basse fréquence: EEClass, ClassLoader et tables de recherche
  4. Stub Heap: stubs pour CAS, wrappers COM, P/Invoke
  5. Large Object Heap: allocation de mémoire nécessitant plus de 85 000 octets
  6. GC Heap: mémoire de tas allouée par l'utilisateur et privée pour l'application
  7. JIT Code Heap: mémoire allouée par mscoreee (Execution Engine) et le compilateur JIT pour le code managé 
  8. Processus/Base Heap: allocations interop/non gérées, mémoire native, etc.

HTH

7
Dave Black

Pour avoir une idée générale de l’allocation de mémoire dans votre application, utilisez la commande sos suivante dans WinDbg.

!dumpheap -stat

Notez que! Dumpheap ne vous donne que les octets du type d'objet lui-même et n'inclut pas les octets de tout autre type d'objet auquel il pourrait faire référence.

Si vous voulez voir le nombre total d'octets détenus (somme de tous les octets de tous les objets référencés par votre objet) d'un type d'objet spécifique, utilisez un profileur de mémoire tel que dot Trace - http://www.jetbrains.com/profiler/

6
Sean

Chaque "classe" nécessite suffisamment de mémoire pour contenir tout le code compilé au format jit pour tous les membres appelés par le runtime (bien que si vous n'appelez pas de méthode pendant un certain temps, le CLR peut libérer cette mémoire et répétez-le si vous l'appelez à nouveau ... plus assez de mémoire pour contenir toutes les variables statiques déclarées dans la classe ... mais cette mémoire n'est allouée qu'une fois par classe, quel que soit le nombre d'instances de la classe que vous créez. 

Pour chaque instance de la classe que vous créez (et n'a pas été récupérée), vous pouvez approximer l'empreinte mémoire en additionnant l'utilisation de la mémoire par chaque variable déclarée basée sur une instance ... (champ) 

les variables de référence (références à d'autres objets) prennent respectivement 4 ou 8 octets (OS 32/64 bits?) int16, Int32, Int64 prennent 2,4 ou 8 octets, respectivement ... 

la variable chaîne prend de la mémoire supplémentaire pour certains métadonnées (plus la taille du pointeur d'adresse) 

De plus, chaque variable de référence dans un objet peut également être considérée comme incluant "indirectement" la mémoire occupée sur le tas par l'objet vers lequel elle pointe, même si vous voudrez probablement compter cette mémoire comme appartenant à cet objet et non à la variable le référence ... 

etc.

6
Charles Bretana

Si vous le pouvez - Sérialisez-le!

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

Il y a la question académique deQuelle est la taille d'un objet à l'exécution?Et c'est intéressant, mais seul un profileur attaché au processus en cours peut y répondre. J'ai passé un bon moment à examiner cela récemment et à déterminer qu'il n'existait aucune méthode générique suffisamment précise et rapide pour que vous souhaitiez l'utiliser dans un système de production. Des cas simples comme des tableaux de types numériques ont des réponses faciles, mais au-delà, la meilleure solution seraitNe cherchez pas à résoudre le problème. Pourquoi voulez-vous savoir cela? Existe-t-il d'autres informations disponibles qui pourraient servir le même objectif?

Dans mon cas, j’ai fini par vouloir répondre à cette question car j’avais plusieurs données utiles, mais que je pouvais ignorer pour libérer RAM de services plus critiques. Les affiches ici sont un Undo Stack et un Cache .

Finalement, j'ai conclu que la bonne façon de gérer la taille de la pile d'annulation et du cache était de demander la quantité de mémoire disponible (il s'agit d'un processus 64 bits, il est donc prudent de supposer que tout est disponible), puis d'autoriser plus d'éléments. à ajouter si la mémoire tampon de RAM est suffisamment grande et que des éléments doivent être supprimés si RAM est en cours d'exécution.

1
briantyler