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)?
Vous pouvez utiliser un profileur de mémoire comme
.NET Memory Profiler ( http://memprofiler.com/ )
ou
CLR Profiler (gratuit) ( http://clrprofiler.codeplex.com/ )
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 ;)
Le profileur de mémoire ANTS vous indiquera exactement le montant alloué pour chaque objet/méthode/etc.
Voici un article connexe où nous avons discuté de la détermination de la taille des types de référence.
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!
EDIT: J'ajoute ce qui suit pour clarifier certaines informations de la réponse fournie par Charles Bretana:
En passant, le CLR utilise environ 8 tas différents:
HTH
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/
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.
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
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.