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 d'approximer) la mémoire attribuée par un objet (instance de classe)?

50
demandé sur Parth Jani 2009-01-09 02:00:46

9 réponses

vous pourriez utiliser un profileur de mémoire comme

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

ou

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

38
répondu Rauhotz 2014-04-28 19:13:17

un moyen grossier pourrait être ceci dans le cas où 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);

peut-être pourrait-on obtenir des produits pour l'ensemble du procédé comme celui-ci

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

espérons que cette aide ;)

36
répondu varun 2015-02-02 21:57:46

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

10
répondu George Stocker 2009-12-16 16:02:49

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

9
répondu John Sheehan 2017-05-23 12:24:38

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

un élément très important à se rappeler est que !objsize vous donne seulement 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 n'ai aucune idée pourquoi il ne fait pas c'est assez frustrant et parfois trompeur.

j'ai créé 2 Suggestions de fonctionnalités sur le site Web Connect qui demandent que cette capacité soit incluse dans VisualStudio. Merci de voter pour les articles que vous aimeriez voir ajoutés ainsi!

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. l'OP a demandé au sujet de la taille d'un "objet" et non de "classe". Un objet est une instance d'une classe. C'est peut-être ce que vous vouliez dire?
  2. la mémoire le code attribué à un objet ne comprend pas le code Jitté. Le code JIT vit dans son propre "tas de Code JIT".
  3. le JIT ne compile le code que selon une méthode par méthode et non au niveau d'une classe. Ainsi, si une méthode n'est jamais appelée pour une classe, elle n'est jamais compilée JIT et n'a donc jamais de mémoire allouée pour elle sur le tas de Code JIT.

à part, il y a environ 8 tas différents que le CLR utilise:

  1. Tas de chargement: contient des structures CLR et le système de type
  2. Haute Fréquence Tas: statique, MethodTables, FieldDescs, interface de carte
  3. Basse Fréquence Tas: EEClass, chargeur de classes et de tables de recherche
  4. Stab Heap: stubs for CAS, COM wrappers, P / Invoke
  5. Gros Tas d'Objets: les allocations de mémoire qui nécessitent plus de 85k octets
  6. GC tas: l'Utilisateur a attribué la mémoire tas privée à la app
  7. tas de Code JIT: mémoire attribuée par mscoreee (moteur D'exécution) et le compilateur JIT pour le code géré
  8. Processus/de la Base du Tas: interop/non géré allocations, natif de la mémoire, etc

HTH

6
répondu Dave Black 2012-08-22 20:50:26

pour obtenir un sens général de l'allocation de mémoire dans votre application, Utilisez la commande sos suivante dans WinDbg

!dumpheap -stat

notez ça !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 (additionner 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 comme Trace point - http://www.jetbrains.com/profiler /

5
répondu Sean 2009-01-09 01:44:22

chaque "classe" a besoin de suffisamment de mémoire pour contenir tout son code JIT-compilé pour tous ses membres qui ont été appelés par l'exécution, (bien que si vous don;t appeler une méthode pendant un certain temps, le CLR peut libérer cette mémoire et le ré-jit si vous l'appelez à nouveau... plus assez de mémoire pour contenir toutes les variables déclarées dans la classe... mais cette mémoire n'est attribuée qu'une fois par classe, peu importe 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é Garbage collected) vous pouvez vous rapprocher de l'empreinte mémoire en additionnant l'utilisation de mémoire par chaque variable déclarée basée sur une instance... (sur le terrain)

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

la variable string prend un stockage supplémentaire pour certains éléments de méta-données, (plus la taille du pointeur d'adresse)

en outre, chaque variable de référence dans un objet pourrait également être considérée comme" indirectement " inclure la mémoire prise sur le tas par l'objet qu'il pointe, bien que vous voudriez probablement compter cette mémoire comme appartenant à cet objet pas la variable qui se réfère...

etc. etc.

5
répondu Charles Bretana 2014-02-24 14:09:05

si vous pouvez-Serialize it!

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
4
répondu serhio 2011-07-05 09:37:18

il y a la question académique de Quelle est la taille d'un objet à l'exécution? et c'est intéressant, mais il ne peut être correctement répondu par un profileur qui est attaché au processus courant. J'ai passé beaucoup de temps à regarder cela récemment et déterminé qu'il n'y a aucune méthode générique qui est précise et assez rapide que vous voudriez jamais l'utiliser dans un système de production. Cas simples comme les tableaux de types numériques ont facile réponses, mais au-delà de cela, la meilleure réponse serait ne vous embêtez pas à essayer de résoudre. Pourquoi voulez-vous savoir cela? Est-il d'autres informations disponibles qui pourraient servir le même but?

dans mon cas, j'ai fini par vouloir répondre à cette question parce que j'avais diverses données qui étaient utiles, mais qui pouvaient être écartées pour libérer la RAM pour des services plus critiques. Les garçons poster 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 undo et du cache était de rechercher la quantité de mémoire disponible (c'est un processus 64 bits donc il est sûr de supposer qu'il est tout disponible) et ensuite permettre plus d'éléments à ajouter s'il y a un tampon de RAM suffisamment grand et exiger des éléments à enlever si la RAM est faible.

0
répondu briantyler 2015-12-09 10:08:32