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)?
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 / )
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 ;)
le profileur de mémoire ANTS vous indiquera exactement combien est alloué pour chaque objet/méthode/etc.
Voici un related post où nous avons discuté de la détermination de la taille des types référence.
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!
EDIT: J'Ajoute ce qui suit pour clarifier certaines informations de la réponse fournie par Charles Bretana:
- 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?
- 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".
- 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:
- Tas de chargement: contient des structures CLR et le système de type
- Haute Fréquence Tas: statique, MethodTables, FieldDescs, interface de carte
- Basse Fréquence Tas: EEClass, chargeur de classes et de tables de recherche
- Stab Heap: stubs for CAS, COM wrappers, P / Invoke
- Gros Tas d'Objets: les allocations de mémoire qui nécessitent plus de 85k octets
- GC tas: l'Utilisateur a attribué la mémoire tas privée à la app
- tas de Code JIT: mémoire attribuée par mscoreee (moteur D'exécution) et le compilateur JIT pour le code géré
- Processus/de la Base du Tas: interop/non géré allocations, natif de la mémoire, etc
HTH
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 /
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.
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
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.