256 votes

Comment obtenir la taille d'un objet en mémoire ?

J'ai besoin de savoir combien d'octets mon objet consomme en mémoire (en C#). Par exemple, combien d'octets ma Hashtable ou SortedList ou List<String> .

3 votes

1 votes

Tout conteneur est un objet relativement petit qui contient une référence à un stockage de données (généralement un tableau) en dehors de l'objet conteneur proprement dit - et qui contient à son tour des références aux objets que vous avez ajoutés au conteneur. Ainsi, la question de savoir combien de mémoire prend une liste n'est même pas bien définie - la taille de l'objet liste lui-même, la mémoire allouée par l'objet liste, la taille totale de tout ce qui est dans la liste et la quantité de mémoire qui sera libérée lorsque la liste sera collectée sont toutes des valeurs différentes.

180voto

rushonerok Points 2753

Ce n'est peut-être pas exact, mais c'est assez proche pour moi.

long size = 0;
object o = new object();
using (Stream s = new MemoryStream()) {
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(s, o);
    size = s.Length;
}

167 votes

Cela va mettre tellement plus. Il ajoute le nom et la version de la DLL, ... ce n'est pas une façon de calculer la taille d'un objet.

10 votes

Je suis d'accord que c'est PAS un bon moyen de calculer la taille d'un objet. La sérialisation peut être une estimation approximative de l'entropie, mais ne fournit aucune information utile sur la consommation de mémoire. Il s'agit d'une question complexe sans solution facile.

72 votes

Je ne pense pas que quiconque se soucie d'obtenir le montant exact de la consommation de mémoire, mais cette méthode est rapide et donne une bonne estimation, d'où le "ce n'est peut-être pas précis, mais c'est assez proche pour moi". pourquoi vous ne proposez pas quelque chose de solide, vous les détracteurs ?

139voto

Rune Grimstad Points 17775

Je ne pense pas que vous puissiez l'obtenir directement, mais il y a quelques façons de le trouver indirectement.

Une façon de procéder est d'utiliser le GC.GetTotalMemory pour mesurer la quantité de mémoire utilisée avant et après la création de votre objet. Ce ne sera pas parfait, mais tant que vous contrôlez le reste de l'application, vous pouvez obtenir les informations qui vous intéressent.

En dehors de cela, vous pouvez utiliser un profileur pour obtenir l'information ou vous pouvez utiliser la fonction api de profilage pour obtenir l'information en code. Mais ce ne sera pas facile à utiliser, je pense.

Ver Découvrez la quantité de mémoire utilisée par un objet en C# ? pour une question similaire.

13 votes

Si la "vraie" réponse peut être "c'est impossible", la meilleure réponse est celle qui vous donne une alternative possible.

0 votes

Cela a bien fonctionné pour moi. Dans mon cas, je travaillais avec un objet très complexe qui ne pouvait pas vraiment être sérialisé facilement, donc le top ans était hors de question. J'ai utilisé cette méthode avec une boucle for pour obtenir une moyenne approximative à chaque point. Cela m'a aidé à voir la différence entre le moment où cette entité n'existait pas et le moment où elle existait. Delta == taille approximative de l'entité.

0 votes

Parfois, j'obtiens un chiffre (qui correspond ensuite à d'autres essais), parfois non. Je voulais juste le signaler. (Peut-être que la GC n'était pas terminée avant de relancer le test ? je ne sais pas... )

51voto

NileshChauhan Points 3126

Objet non géré :

  • Marshal.SizeOf(object yourObj);

Types de valeurs :

  • sizeof(object val)

Objet géré :

3 votes

Le lien est mort, pouvez-vous modifier votre réponse ?

1 votes

C'est intéressant ; j'ai vérifié Marshal.SizeOf(<variable bool set to false>) et cela m'a donné 4... pourquoi si les bools ont une taille de 1 ?

2 votes

Je pense qu'il y a un bit pertinent mais le framework utilise toujours les 4bytes ou 8bytes (en fonction de votre architecture) ..... Vous pouvez lire une explication détaillée ici quora.com/

29voto

Aliostad Points 47792

OK, cette question a été répondue et la réponse a été acceptée mais quelqu'un m'a demandé de mettre ma réponse alors voilà.

Tout d'abord, il n'est pas possible de l'affirmer avec certitude. Il s'agit d'un détail d'implémentation interne et non documenté. Cependant, en se basant sur les objets inclus dans l'autre objet. Maintenant, comment calculer le besoin en mémoire pour nos objets en cache ?

J'avais déjà abordé ce sujet dans ce article :

Maintenant, comment calculer le besoin en mémoire pour notre cache en cache ? Eh bien, comme la plupart d'entre vous le savent, Int32 et float sont des objets de quatre octets, double et DateTime 8 octets, char est en réalité deux octets (et non pas un octet), et ainsi de suite. String est un peu plus complexe, 2*(n+1), où n est la longueur de la chaîne. Pour les objets, cela dépendra de leurs membres : il suffit d'additionner les besoins en mémoire de tous ses membres, en se rappelant que toutes les références d'objets sont simplement des pointeurs de 4 octets sur une boîte 32 bit. Maintenant, ce n'est pas tout à fait vrai, nous n'avons pas pris en compte de l'overhead de chaque objet dans le tas. Je ne suis pas sûr que vous ayez besoin si vous devez vous en préoccuper, mais je suppose que si vous utilisez beaucoup de petits objets, vous devriez prendre l'overhead en considération. considération. Chaque objet du tas coûte autant que ses types primitifs, plus quatre octets pour les références aux objets (sur une machine 32 bits, bien que BizTalk fonctionne en 32 bits sur des machines 64 bits également), plus 4 octets pour le pointeur d'objet de type, et je pense 4 octets pour l'index de bloc de synchronisation. Pourquoi cette surcharge supplémentaire est-elle importante ? Eh bien, imaginons que nous ayons une classe avec deux membres Int32 ; dans ce cas, le besoin en mémoire est le suivant 16 octets et non 8.

7 votes

Cela ne répond pas à la question de l'OP, comment sommes-nous censés mesurer la taille d'un HashSet par rapport à une liste ?

0 votes

@yoelhalb - il répond effectivement, et de manière assez précise. Il n'y a pas de réponse unique ou courte à la question.

19voto

Kevin Hirst Points 127

Le fragment de code suivant devrait renvoyer la taille en octets de tout objet qui lui est passé, pour autant qu'il puisse être sérialisé. J'ai obtenu cela d'un collègue de Quixant pour résoudre un problème d'écriture en SRAM sur une plateforme de jeu. J'espère que cela vous aidera. Crédit et remerciements à Carlo Vittuci.

/// <summary>
/// Calculates the lenght in bytes of an object 
/// and returns the size 
/// </summary>
/// <param name="TestObject"></param>
/// <returns></returns>
private int GetObjectSize(object TestObject)
{
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    byte[] Array;
    bf.Serialize(ms, TestObject);
    Array = ms.ToArray();
    return Array.Length;
}

2 votes

Ça n'a pas marché pour moi. La classe de l'objet n'était pas définie comme sérialisable et le message "Not marked as serializable error" est apparu.

2 votes

Bonjour @Kevin Hirst, j'ai essayé avec ceci qui a analysé mon jeu de données pour obtenir la taille en octets. Il m'a renvoyé l'exception Out of memory. J'ai découvert que la taille maximale des octets est de 2 Go ? Avez-vous une idée de la façon de gérer cela ?

0 votes

@Worgon, avez-vous vraiment besoin de connaître la taille de votre ensemble de données, sauf à des fins d'investigation ? Je préfère réfléchir à un niveau, pour éliminer une telle nécessité. Si vous insistez, vous pourriez penser à mesurer la taille d'un ensemble de données particulier ou utiliser les méthodes de calcul mentionnées ci-dessus. GC.GetTotalMemory approche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X