7
votes

Grand heap objet fragmentation: CLR y a une solution?

Si votre application est telle qu'elle doit faire beaucoup d'allocation / désaffectation d'objets de grande taille (> 85 000 octets), sa fragmentation de la mémoire entraînera une fragmentation de la mémoire et vous lancera une exception hors mémoire.

Y a-t-il une solution à ce problème ou est-ce une limitation de la gestion de la mémoire CLR?


2 commentaires

Notez que le seuil de tas de tas de gros objet est des allocations de 85 000 octets chacun, pas de 85 octets chacun. Suggère d'éditer votre question si c'était une faute de frappe. (et envisagez la question si ce n'était pas)


@Aliostad: msdn.microsoft.com/en-us/magazine/cc534993.aspx


6 Réponses :


7
votes

Malheureusement, toutes les informations que j'ai jamais vues ne suggèrent que la gestion des facteurs de risque vous-même: réutilisez les gros objets, allouez-les au début, assurez-vous qu'ils sont des tailles de multiples les uns des autres, utilisez des structures de données alternatives (listes , arbres) au lieu de tableaux. Cela vient de me donner une autre idée de créer une liste de non-fragmentation qu'au lieu d'un grand tableau, se divise en plus petits. Les tableaux / listes semblent être les plus fréquents Culprits IME.

Voici un article de magazine MSDN à ce sujet: http://msdn.microsoft.com/en-us/magazine/cc534993.aspx , mais il n'y a pas beaucoup d'utile.


0 commentaires

2
votes

Un programme Toujours des bombes sur OOM, car il demande un morceau de mémoire trop grand, jamais parce qu'il épuisait complètement tous les espaces d'adresses de mémoire virtuelle. Vous pouvez soutenir que c'est un problème avec le loh d'être fragmenté, il est tout aussi facile de faire valoir que le programme utilise trop de mémoire virtuelle.

Une fois qu'un programme va au-delà de l'allocation de la moitié de la mémoire virtuelle adressable (un gigaoctet), il est vraiment temps de prendre en compte la création de son code plus intelligent afin de ne pas gonfler autant de mémoire. Ou faire un système d'exploitation de 64 bits une condition préalable. Ce dernier est toujours moins cher. Il ne sort pas de votre poche non plus.


1 commentaires

Totalement d'accord avec vous sur 64 bits d'os, mais je souhaite que tous mes clients soient disposés à améliorer leurs ordinateurs en fonction de cette justification :) Nous vivons dans un monde difficile



3
votes

La chose à propos des gros objets du collecteur des ordures du CLR est qu'ils sont gérés dans un tas différent. Le collecteur des ordures utilise un mécanisme appelé "compactage", qui est essentiellement une fragmentation et une nouvelle liaison des objets dans le tas régulier. La chose est, puisque "compacter" de gros objets (la copie et les reliant) est une procédure coûteuse, le GC fournit un tas différent pour eux, que n'est jamais compacté.

Notez également que l'allocation de mémoire est contiguë. Signification Si vous allouez l'objet n ° 1, puis objet n ° 2, l'objet n ° 2 sera toujours être placé après l'objet n ° 1.

Ceci est probablement ce qui vous oblige à sortir de MemororyExceptions.

Je suggérerais d'examiner les modèles de conception tels que Flyweight, l'initialisation paresseuse et la piscine d'objets.

Vous pouvez également forcer la collection de GC, si vous soupçonnez que certains de ces gros objets sont déjà morts et que vous n'avez pas été collectés en raison de défauts dans votre flux de contrôle, les faisant atteindre des générations supérieures juste avant d'être prêt pour la collecte .


2 commentaires

Les gros objets ne piste pas des générations, elles ne sont collectées que lors des collections complètes.


"Signification Si vous allouez l'objet n ° 1, puis l'objet n ° 2, l'objet n ° 2 sera toujours placé après l'objet n ° 1" - pour clarifier: Si vous êtes libre objet # 1 d'abord, et sa taille est> = objet n ° 2, puis le CLR peut l'allouer dans l'espace précédemment utilisé par l'objet n ° 1.



1
votes
Is there any solution to this problem or is it a limitation of CLR memory management?
There is no solution besides reconsidering your design. And it is not a problem of the CLR. Note, the problem is the same for unmanaged applications. It is given by the fact, that too much memory is used by the application at the same time and in segments laying 'disadvantageous' out in memory. If some external culprit has to be pointed at nevertheless, I would rather point at the OS memory manager, which (of course) does not compact its vm address space. The CLR manages free regions of the LOH in a free list. This in most cases is the best what can be done against fragmentation. But since for really large objects, the number of objects per LOH segment decreases - we eventually end up having only one object per segment. And where those objects are positioned in the vm space is completely up to the memory manager of the OS. This means, the fragmentation mostly happens on the OS level - not on the CLR. This is an often overseen aspect of heap fragmentation and it is not .NET to blame for it. (But it is also true, fragmentation can also occour on the managed side like nicely demonstrated in that article.) Common solutions have been named already: reuse your large objects. I up to now was not confronted with any situation, where this could not be done by proper design. However, it can be tricky sometimes and therefore may be expensive though. 

0 commentaires

-1
votes

J'ai vu dans une réponse différente que le loh puisse réduire la taille:

Grands tableaux et fragmentation LOH. Quelle est la convention acceptée?

" ... Maintenant, après avoir dit que le LOH peut réduire de taille si la zone à sa fin est complètement exempte d'objets en direct, le seul problème est donc si vous laissez des objets là-bas pendant une longue période (par ex. La durée de l'application). ... "

Autre alors que vous pouvez faire fonctionner votre programme avec une mémoire étendue jusqu'à 3 Go sur un système 32 bits et jusqu'à 4 Go sur un système 64 bits. Il suffit d'ajouter le drapeau / Largeaddressaware dans votre lieur ou cet événement de publication:

appel "$ (devenvdiir) .. \ outils \ vsvars32.bat" Editbin / largeadddressaware "$ (Targepath)"

En fin de compte Si vous envisagez d'exécuter le programme pendant une longue période avec de nombreux objets volumineux, vous devrez optimiser l'utilisation de la mémoire et vous devrez même avoir à réutiliser des objets alloués pour éviter les poubelles similaires dans le concept, travailler avec des systèmes de temps réel.


0 commentaires

0
votes

Nous étions préessions des images dans plusieurs threads. Avec des images suffisamment grandes, cela a également causé des exceptions exceptionnelles en raison de la fragmentation de la mémoire. Nous avons essayé de résoudre le problème en utilisant la mémoire dangereuse et en pré-allocant des tas pour chaque thread. Malheureusement, cela n'a pas été complètement aidé depuis que nous nous sommes comptabilisés sur plusieurs bibliothèques: nous avons pu résoudre le problème dans notre code, mais pas la tierce partie.

Finalement, nous avons remplacé les threads avec des processus et laissez le système d'exploitation faire le travail acharné. Les systèmes d'exploitation ont construit depuis longtemps une solution pour la fragmentation de la mémoire, il est donc imprudent de l'ignorer.


0 commentaires