37 votes

.Net 4 Fuites MemoryCache avec récupération de place concurrente

Je suis l'aide de la nouvelle MemoryCache dans .Net 4, avec un max de cache de limite de taille en MO (je l'ai testé comprise entre 10 et 200 MO, sur les systèmes avec entre 1,75 et de 8 go de mémoire). Je n'ai pas mis tout moment, en fonction d'expiration sur les objets, comme je suis en utilisant le cache simplement comme un disque dur haute performance, et tant qu'il y a de l'espace, je veux qu'il a utilisés. À ma grande surprise, le cache a refusé d'expulser tout les objets, au point que j'aurais SystemOutOfMemory des exceptions.

J'ai tiré jusqu' perfmon, wired up ma demande d' .Net CLR Memory\#Bytes In All Heaps, .Net Memory Cache 4.0, et Process\Private Bytes -- en effet, la consommation de mémoire est hors de contrôle, et pas de cache garnitures ont été enregistrés.

Fait quelques recherches sur google et stackoverflowing, téléchargé et attaché le CLRProfiler, et wham: les expulsions partout! Le souvenir est resté dans des limites raisonnables basées sur la taille de la mémoire de la limite que j'avais fixé. Il a couru en mode de débogage, de nouveau, pas d'expulsions. CLRProfiler de nouveau, les expulsions.

J'ai finalement remarqué que le profileur forcée de l'exécution de l'application sans simultanées de collecte des ordures (voir aussi utile de manière Simultanée la Collecte des Ordures Question). Je l'ai désactivé dans mon application.config, et, bien sûr, les expulsions!

Cela semble être, au mieux, un scandaleux manque de documentation pour ne pas dire: cela ne fonctionne qu'avec la non-concordance de collecte des ordures -- si j'ai l'image depuis sa porté à partir de ASP.NET ils n'auront pas eu à se soucier simultanées de collecte des ordures.

Si quelqu'un d'autre a vu cela? J'aimerais obtenir quelques autres expériences là-bas, et peut-être plus instruits idées.


Mise à jour 1

J'ai reproduit le problème au sein d'une seule méthode: il semble que le cache doit être écrit en parallèle pour le cache des expulsions de ne pas le feu (simultané de collecte des ordures mode). Si il y a un certain intérêt, je vais télécharger le code de test pour un public de pensions. Je suis certainement vers l'extrémité profonde de la le CLR/GC/MemoryCache de la piscine, et je crois que j'ai oublié mon floaties...


Mise à jour 2

J'ai publié un code de test sur CodePlex à reproduire le problème. Aussi, éventuellement, de l'intérêt, de la production originale, le code est exécuté dans Azure, comme un Rôle de Travailleur. Intéressant, la modification de la GC de la simultanéité de réglage dans le rôle de l'app.config n'a aucun effet. Éventuellement Azure remplace GC paramètres comme ASP.NET? En outre, l'exécution, le code de test sous WPF vs une application de Console va produire légèrement différente expulsion des résultats.

8voto

Teoman Soygul Points 17544

Vous pouvez "forcer" une récupération de mémoire juste après la méthode problématique et voir si le problème se reproduit en exécutant:

 System.Threading.Thread.Sleep(200);
GC.Collect();
GC.WaitForPendingFinalizers();
 

à la fin de la méthode (assurez-vous de libérer tous les descripteurs pour référencer les objets et les annuler). Si cela empêche les fuites de mémoire, alors oui, il peut y avoir un bogue d'exécution.

4voto

supercat Points 25534

Cessez-le-monde-de la collecte des ordures est basé sur de déterminer si une forte vivent référence à un objet existant au moment où le monde est arrêté. Concurrente de la collecte des ordures généralement détermine si une forte vivent référence à un objet existe depuis quelques temps dans le passé. Ma conjecture serait que de nombreuses références à des objets détenus dans WeakReferences sont créés individuellement et jetés. Si un cessez-le-monde garbage collector feux entre le moment où un objet est créé et le temps, il est mis au rebut, cet objet sera gardé en vie, mais déjà jeté des objets ne sera pas. En revanche, un concurrent à l'garbage collector peut pas détecter que toutes les références à un objet ont été rejetées jusqu'à ce qu'une certaine quantité de temps qui passe sans de solides références à l'objet en cours de création.

J'ai parfois souhaité que .net serait d'offrir quelque chose entre une référence forte et faible, qui permettrait d'éviter un objet d'être effacés de la mémoire, mais ne devrait pas l'empêcher d'être finalisé ou à faible WeakReferences à la nullité. Ces références n'légèrement compliquer la GC, d'où la nécessité de chaque objet à séparer les drapeaux indiquant si forte et quasi-références faibles existent pour elle, et si elle a été numérisée pour à la fois forte et quasi-références faibles, mais une telle fonctionnalité pourrait être utile dans de nombreuses "la faiblesse de l'événement" les scénarios.

2voto

miwingman Points 21

J'ai trouvé cette entrée tout en recherchant un sujet similaire et je me concentre sur votre Mémoire exception.

Si vous mettez un objet dans le cache alors elle n'est peut-être référence à d'autres objets et, par conséquent, ces objets ne seraient pas les ordures collectées, d'où le manque de mémoire exception et sans doute un CPU étant fixé à raison de la Gen 2 de collecte des ordures.

Êtes-vous de mettre "utilisé" des objets sur le cache ou les clones de "servir" des objets sur le cache? Si vous mettez un clone sur le cache puis le "utilisé" l'objet que des références à d'autres objets pourraient être nettoyée.

Si vous éteignez votre mécanisme de mise en cache est-ce que votre programme encore exécuté de mémoire? Si ce n'est pas à court de mémoire alors que tendrait à prouver que les objets que vous auriez normalement mettre sur le cache tiennent toujours des références à d'autres objets qui entravent la collecte des ordures.

Forcer la collecte des ordures n'est pas recommandée et ne doit pas être fait. Dans ce scénario, les obligeant à une collecte des ordures ne jetez pas les objets référencés de toute façon.

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