J'ai lu sur les générations et le tas d'objets volumineux. Mais je ne comprends toujours pas quelle est la signification (ou l'avantage) d'avoir un tas d'objets de grande taille?
Qu'est-ce qui aurait pu mal tourner (en termes de performances ou de mémoire) si CLR s'était simplement appuyé sur la génération 2 (étant donné que le seuil pour Gen0 et Gen1 est petit pour gérer les grands objets) pour stocker de gros objets?
.net
garbage-collection
clr
large-object-heap
Manish Basantani
la source
la source
Réponses:
Un garbage collection ne se débarrasse pas seulement des objets non référencés, il compacte également le tas. C'est une optimisation très importante. Cela ne rend pas seulement l'utilisation de la mémoire plus efficace (pas de trous inutilisés), cela rend le cache du processeur beaucoup plus efficace. Le cache est un très gros problème sur les processeurs modernes, ils sont d'un ordre de grandeur facile plus rapides que le bus mémoire.
Le compactage se fait simplement en copiant des octets. Cela prend cependant du temps. Plus l'objet est grand, plus il est probable que le coût de sa copie l'emporte sur les améliorations possibles de l'utilisation du cache du processeur.
Ils ont donc exécuté une série de points de repère pour déterminer le seuil de rentabilité. Et arrivé à 85 000 octets comme point de coupure où la copie n'améliore plus les performances. Avec une exception spéciale pour les tableaux de double, ils sont considérés comme «grands» lorsque le tableau contient plus de 1000 éléments. C'est une autre optimisation pour le code 32 bits, l'allocateur de tas d'objets volumineux a la propriété spéciale d'allouer de la mémoire à des adresses alignées sur 8, contrairement à l'allocateur générationnel régulier qui alloue uniquement aligné sur 4. Cet alignement est un gros problème pour le double , lire ou écrire un double mal aligné coûte très cher. Curieusement, les informations Microsoft clairsemées ne mentionnent jamais de tableaux de longue durée, je ne sais pas ce qui se passe avec cela.
Fwiw, il y a beaucoup d'angoisse du programmeur à propos du gros tas d'objets qui ne soit pas compacté. Cela se déclenche invariablement lorsqu'ils écrivent des programmes qui consomment plus de la moitié de tout l'espace d'adressage disponible. Suivi en utilisant un outil comme un profileur de mémoire pour découvrir pourquoi le programme a bombardé même s'il y avait encore beaucoup de mémoire virtuelle inutilisée disponible. Un tel outil montre les trous dans la LOH, des blocs de mémoire inutilisés où auparavant un gros objet vivait mais était récupéré. Tel est le prix inévitable du LOH, le trou ne peut être réutilisé que par une allocation pour un objet de taille égale ou inférieure. Le vrai problème est de supposer qu'un programme devrait être autorisé à consommer toute la mémoire virtuelle à tout moment.
Un problème qui, autrement, disparaît complètement en exécutant simplement le code sur un système d'exploitation 64 bits. Un processus 64 bits a 8 téraoctets d'espace d'adressage de mémoire virtuelle disponibles, 3 ordres de grandeur de plus qu'un processus 32 bits. Vous ne pouvez tout simplement pas manquer de trous.
Pour faire court, la LOH rend le code plus efficace. Au détriment de l'utilisation de l'espace d'adressage de la mémoire virtuelle disponible moins efficace.
UPDATE, .NET 4.5.1 prend désormais en charge le compactage de la propriété LOH, GCSettings.LargeObjectHeapCompactionMode . Méfiez-vous des conséquences s'il vous plaît.
la source
Si la taille de l'objet est supérieure à une valeur épinglée (85 000 octets dans .NET 1), CLR le place dans le tas d'objets volumineux. Cela optimise:
jamaisrarement compactée)la source
La différence essentielle entre Small Object Heap (SOH) et Large Object Heap (LOH) est que la mémoire dans SOH est compactée lors de la collecte, alors que LOH non, comme cet article illustre . Le compactage d'objets volumineux coûte cher. Similaire aux exemples de l'article, disons que le déplacement d'un octet en mémoire nécessite 2 cycles, puis le compactage d'un objet de 8 Mo dans un ordinateur à 2 GHz nécessite 8 ms, ce qui représente un coût élevé. Étant donné que les objets volumineux (tableaux dans la plupart des cas) sont assez courants dans la pratique, je suppose que c'est la raison pour laquelle Microsoft épingle de gros objets dans la mémoire et propose LOH.
BTW, selon ce post , LOH ne génère généralement pas de problèmes de fragments de mémoire.
la source
Le principe est qu'il est peu probable (et peut-être mal conçu) qu'un processus crée de nombreux objets volumineux de courte durée, de sorte que le CLR alloue des objets volumineux à un tas séparé sur lequel il exécute GC selon une planification différente de celle du tas normal. http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
la source
Je ne suis pas un expert du CLR, mais j'imagine que le fait d'avoir un tas dédié pour les gros objets peut empêcher des balayages GC inutiles des tas générationnels existants. L'allocation d'un objet volumineux nécessite une quantité importante de mémoire libre contiguë . Afin de fournir cela à partir des "trous" dispersés dans les tas générationnels, vous auriez besoin de compactions fréquentes (qui ne sont effectuées qu'avec des cycles GC).
la source