Explicitement la libération de la mémoire en c#
J'ai créer une application en c# qui utilise jusqu'à 150 mo de mémoire (en octets privés), principalement en raison d'un gros dictionnaire:
Dictionary<string, int> Txns = new Dictionary<string, int>();
Je me demandais comment faire pour libérer cette mémoire. J'ai essayé ceci:
Txns = null;
GC.Collect();
Mais il ne semble pas faire beaucoup de trou dans ma octets privés - ils abandonnent de dire 155mb à 145mb.
Toute indices?
Grâce
-edit-
Bon, je vais avoir plus de chance avec ce code (il reçoit les octets privés vers le bas à 50 mo), mais pourquoi?
Txns.Clear(); //<- makes all the difference
Txns = null;
GC.Collect();
-edit-
Bon pour tout le monde qui dit " ne pas utiliser GC.collect", juste assez (je ne vais pas le débat, autre que de dire que vous pouvez le voir mon C en arrière-plan à venir à travers, mais il n'a pas vraiment répondu à ma question:
Pourquoi ne le garbage collector seulement de libérer de la mémoire, si je la liste des transactions en premier? Ne devrait-il pas libérer de la mémoire, de toute façon, depuis le dictionnaire a été déréférencé?
- GC.Collect() ne pas appliquer que la quantité de mémoire qui pourrait être recueillis sont recueillies lors de la collecte des déchets est un processus multi-étapes. Un processus que je pourrais ajouter que vous n'avez généralement pas besoin de savoir les détails à propos de...
- Est-il nécessaire de mettre en Txns null, ça va faire une différence? ou tout simplement de Compensation le contenu est assez(pour libérer de la mémoire)?
Vous devez vous connecter pour publier un commentaire.
Octets privés reflètent le processus de " l'utilisation de la mémoire. Lorsque les objets sont recueillis à la mémoire associée à l'segment peut ou ne peut pas être libéré de l'OS. Le CLR qui gère la mémoire au niveau de l'OS et puisque l'allocation et la libération de la mémoire n'est pas gratuit, il n'y a aucune raison pour gratuit chaque morceau de la mémoire, comme les chances sont que l'application sera probablement demande plus de mémoire plus tard.
si u appel GC.Collect() elle commence à faire son travail , mais il revient tout de suite, il ne marche pas de bloc, de sorte que vous ne voyez pas de ses effets, si vous appelez GC.WaitForPendingFinalizers() après qu'elle bloquera votre application jusqu'à la GC.Collect() terminer son travail
La plupart vous avez probablement caché de référence pour le dictionnaire à un autre endroit. Ainsi, le dictionnaire n'est pas collectée, mais si vous
Clear()
, le contenu obtenir recueillies.Comme d'autres l'ont déjà noté, forçant le GC n'est pas recommandé. Cela pourrait conduire à la mémoire d'être poussé vers la plus "générations" qui ne sont pas souvent recueillies, et ainsi de gaspiller plus de mémoire que gagner dans le long terme.
Pas sûr à partir de la mémoire si
Dictionary
a unDispose()
ou pas, mais il est lié à uneClear()
. Appelez une de ces avant de régler les références ànull
.Ensuite, il suffit de laisser le garbage collector de faire son travail. Il est presque jamais une bonne idée d'appeler
GC.Collect()
explicitement, de vous-même et il pourrait même ne pas faire ce que vous voulez/besoin d ' /attendre et de vous coûter la performance. L'Analyse statique de Code (=FxCop) ne vous avertit avec La fiabilité de la règle CA2001 sur cela pour rien, vous savez? Il suffit de ne pas le faire sauf si vous savez vraiment ce que vous faites. Et même alors, ne pas le faire. 😉Êtes-vous sûr que le dictionnaire est énorme? N'est-il pas juste 10 Mo de mémoire et le reste est pris par votre application? Question qui pourrait vous aider: Avez-vous utilisé un profiler encore de voir où la mémoire est effectivement consommée...?
Edit:
Pour être juste, la définition de la référence à la valeur null ne libère pas la mémoire, il attribue à son conteneur à une adresse différente, dans ce cas, la valeur null. Selon MSDN, appelant
Clear()
, fait ceci: "Le Comte de la propriété est définie sur 0, et des références à d'autres objets à partir d'éléments de la collection sont également libérés. La capacité reste inchangée."...
Vous devriez ne jamais appeler le garbage collector. Vous utilisez des objets gérés sans ressources autochtones, la confiance, la collecte des déchets à nettoyer après vous.
En fonction de la taille de votre dictionnaire, vous n'avez pas besoin de vous soucier de mémoire, la mémoire n'est pas votre problème, c'est les éboueurs problème.
Appel
Clear()
va supprimer les références à tout objet contenu à l'intérieur, mais la capacité reste inchangé.Sur une note plus technique, la collecte de la mémoire est cher et beaucoup de temps d'exploitation. Raison d'être, non seulement le GC poignée de segment de mémoire et de nettoyer votre tas, elle aussi défragmente le tas. Il tente de passer de la mémoire en blocs contigus à la vitesse maximum de l'allocation pour quand un morceau de code fait une demande importante.
p.s. Quelle est la taille de votre dictionnaire que vous utilisez 155MB de la mémoire?
Vous avez besoin de la mémoire? Le mémoire est disponible, c'est juste pas être récupérée. Vous ne devez pas effacer le dictionnaire, tenir une référence faible et de laisser l'exécution faire son travail.
Si vous voulez voir de très profond dans ce qui se passe, consultez la .NET Memory Profiler. Qui va vous donner de la visibilité dans exactement ce qui se passe avec votre objet, ce que génération c'est ce que la mémoire est utilisée par les ce et sur et sur. 🙂
Ok, j'ai une théorie là...
Le dictionnaire est une collection de KeyValuePair qui est encore une fois un type de référence.
Votre dictionnaire contient ces keyValuePairs. Quand vous dites:
Il libère la référence "Txns" de ceux KeyValuePair collection. Mais encore la mémoire réelle de 150 Mo est référencé par ceux KeyValuePair et ils sont dans le champ d'application, ce n'est pas prêt pour la collecte des ordures.
Mais lorsque vous utilisez la commande suivante:
Ici, la méthode clear libère également l'150 mo de données à partir de leurs propres KeyValuePair les références de l'objet. Ainsi, ces objets étaient prêts pour la collecte des ordures.
C'est juste un sauvage suppose que je fais ici. Les commentaires sont les bienvenus 🙂
var arrayOfReferencesToKeyValuePairs = Txns.ToArray();
Dans son scénario, une foisTxns
est null, il n'y a aucun moyen d'accéder à de l'KeyValuePairs et le garbage collector le voit.Windows a deux la mémoire des événements de disponibilité. Je m'attends à de la CLR pour répondre à cette question. Si il y a suffisamment de mémoire disponible, la chose la plus intelligente est de ne PAS courir le garbage collector. Donc, assurez-vous que vous êtes, en effet, l'observation de mauvais CLR comportement, veuillez répéter le test avec une autre application factice à l'aide d'un gros tas de mémoire.
Il n'est généralement pas une bonne idée d'essayer de forcer la GC. Avez-vous vraiment besoin de l'ensemble de dictionnaire en mémoire?