Question

J'ai une application qui lit une grande quantité de files d'attente MSMQ (environ 10 000 pour le moment).j'utilise queue.BeginPeek avec délai d'expiration UInt32.MaxValue pour recevoir le message de la file d'attente.Lorsque le message apparaît dans la file d'attente, je le traite et j'appelle queue.BeginPeek encore.J'écoute donc toutes les files d'attente, mais le traitement des messages se fait sur Thread Pool.

J'ai remarqué que l'utilisation de la mémoire augmente lentement (deux semaines de travail entraînent une croissance de 200 Mo à 800 Mo).Après avoir étudié le fichier de vidage, je vois une image typique de fragmentation de tas avec de nombreux objets libres (certains d'entre eux ont une taille d'environ plusieurs mégaoctets).Et il y a des objets épinglés entre les trous.

Cela semble être une situation courante lorsque vous travaillez avec des appels à du code non géré, qui créent des objets épinglés.Mais je n'ai trouvé aucune solution sur Internet.

Alors, la gestion de la mémoire dans .NET est-elle si pure qu'elle ne permet pas de réaliser même des scénarios aussi simples, ou quelque chose me manque ?

Modifier : J'ai fait quelques recherches sur des exemples d'applications.Les trous (zones de mémoire libres, appelées objets libres) entre les objets épinglés sont réutilisés par GC lors de l'allocation de mémoire pour de nouveaux objets.Mais dans mon application de production, les objets épinglés durent longtemps et ils apparaissent finalement dans la 2ème génération avec les trous entre eux (car GC ne fait que déplacer la frontière qui sépare les générations).Comme j'ai très peu d'objets normaux à longue durée de vie, je vois ces trous dans la 2ème génération dans le fichier de vidage.

La consommation mémoire de mon application peut donc atteindre 10 000* (taille moyenne du trou).(10 000 est le nombre de files d’attente qui pourrait également augmenter à l’avenir).Je n'ai aucune idée de comment résoudre ce problème pour le moment.Le seul moyen est de redémarrer l'application de temps en temps.

Encore une fois, je ne peux que demander pourquoi .NET n'a pas de tas séparé pour les objets épinglés ?(c'est peut-être une question de débutant).Pour le moment, je constate que l'appel d'opérations asynchrones fonctionnant avec du code non géré peut entraîner des problèmes de mémoire.

Était-ce utile?

La solution

Après avoir examiné le code source du wrapper géré pour MSMQ, il semble que vous soyez tombé sur un véritable problème lors de l'utilisation de l'API.Appel BeginPeek créera une collection de propriétés qui seront ensuite épinglées avant de passer à l'API non gérée.Ce n'est que lorsqu'un message est reçu que ces propriétés sont désépinglées, mais pour continuer à recevoir des messages, vous devez appeler BeginPeek à ce stade, conduisant à une fragmentation de la mémoire au fil du temps.

Si cette fragmentation est un réel problème, le seul hack que je puisse proposer est d'annuler tous les heures environ toutes les heures. BeginPeek, forcez un garbage collection, puis reprenez les opérations d'écoute normales.Cela devrait permettre au garbage collector de gérer la fragmentation.

Autres conseils

Eh bien, s'il s'agit d'un problème lié à la longue durée de vie des objets épinglés, une solution simple consisterait à utiliser un délai d'attente sur le BeginPeek avec une durée plus courte pour les empêcher de passer à la génération suivante.Après chaque temps mort et EndPeek vous pouvez rééditer le BeginPeek.En fonction du moment où les propriétés auxquelles Martin a fait référence sont créées et supprimées, vous devrez peut-être recréer l'objet de file d'attente (pas la file d'attente elle-même évidemment, juste le wrapper modifié).Mais avec de la chance, vous n’aurez pas à aller aussi loin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top