Existe-t-il un moyen de détecter la fragmentation de la mémoire sur Linux? En effet, sur certains serveurs de course à pied, j'ai remarqué une dégradation des performances et seulement après avoir redémarré le processus, je vois de meilleures performances. Je l'ai remarqué plus lors de l'utilisation de Support Linux énorme de page - sont d'énormes pages de Linux plus sujettes à la fragmentation?
J'ai examiné/proc/buddyinfo en particulier. Je veux savoir s'il y a de meilleurs moyens (pas seulement des commandements de CLI en soi, tout programme ou des antécédents théoriques feraient) de le regarder.
Je réponds à la balise - Linux . Ma réponse est spécifique uniquement à Linux.
Oui, d'énormes pages sont plus sujets à la fragmentation. Il y a deux vues de mémoire, celle de votre processus (virtuel) et celui que le noyau gère (réel). Plus n'importe quelle page, plus il sera difficile de regrouper (et de le garder avec) ses voisins, surtout lorsque votre service est en cours d'exécution sur un système qui doit également prendre en charge les autres que par défaut allouer et écrire à bien plus de mémoire que nécessaire effectivement finir par utiliser.
La cartographie du noyau d'adresses accordées (réelles) est privée. Il y a une très bonne raison pour laquelle les utilisateurs les voit alors que le noyau les présente, car le noyau doit pouvoir surmonter sans entouré d'espace utilisateur déroutant. Votre processus obtient une belle contiguë "Disneyfied" Espace d'adresse dans laquelle travailler, inconscient de ce que le noyau est en fait faire Avec cette mémoire dans les scènes.
La raison pour laquelle vous voyez des performances dégradées sur des serveurs de longueur longue est probablement car les blocs alloués qui n'ont pas été explicitement verrouillés (par exemple, mlock()
/mlockall()
ou posix_madvise()
) et non modifié depuis un moment ont été PAGED OUT, ce qui signifie que vos dérapent votre service sur disque lorsqu'il doit les lire. Modification de ce comportement fait votre processus A Bad voisin, c'est pourquoi de nombreuses personnes mettent leur SGBDM sur un serveur complètement différent de Web/PHP/Python/RUBY/PYTHON/RUBY/PLYON/PHP. Le seul moyen de résoudre ce problème, sanely, est de réduire la concurrence des blocs contigus.
La fragmentation n'est que vraiment perceptible (dans la plupart des cas) lorsque la page A est en mémoire et la page B a été déplacée pour échanger. Naturellement, le nouveau démarrage de votre service semblerait "guérir" ceci, mais seulement parce que le noyau n'a pas encore eu l'occasion de parcourir les blocs de processus "(maintenant) nouvellement attribués dans les limites de son ratio de surcommande.
En fait, redémarrez (disons) 'Apache' sous une charge élevée va probablement envoyer des blocs appartenant à d'autres services directement sur le disque. Donc, oui, "Apache" s'améliorerait pendant une courte période, mais "mysql" pourrait souffrir. Au moins jusqu'à ce que le noyau les fait souffrir de manière égale quand il y a simplement un manque de mémoire physique.
Ajoutez plus de mémoire ou divisez-vous exigeant malloc()
Consommateurs :) sa fragmentation non seulement que vous devez regarder.
Essayez vmstat
_ Pour obtenir un aperçu de ce qui est réellement stocké où.
Pour obtenir une utilisation actuelle de l'indice de fragmentation:
Sudo cat /sys/kernel/debug/extfrag/extfrag_index
Pour défragmenter la mémoire du noyau, essayez d'exécuter:
sysctl vm.compact_memory=1
Vous essayez également d'éteindre les énormes pages transparentes (AKA THP) et/ou désactiver le swap (ou diminuer swappiness
).
Pour réduire la fragmentation de l'espace utilisateur, vous voudrez peut-être essayer différents allocator, par exemple. jemalloc
(il a de grandes capacités d'introspection , qui vous donnera une fragmentation interne d'allocator).
Vous pouvez passer à Custom Malloc en recompilant votre programme avec elle ou simplement en exécutant votre programme avec LD_PRELOAD
: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app
(Méfiez-vous d'interactions entre les allocateurs de mémoire THP et de mémoire )
Bien que, légèrement sans rapport avec la fragmentation de la mémoire (mais connectée à la compactage/migration de la mémoire), vous souhaitez probablement exécuter plusieurs instances de votre service, une pour chaque nœud numa et les lier à l'aide de numactl
.
L'utilisation d'énormes pages ne doit pas causer de fragmentation de mémoire supplémentaire sur Linux; La prise en charge de Linux pour les pages énormes n'est que pour la mémoire partagée (via shmget ou MMAP) et toutes les pages énormes utilisées doivent être spécifiquement demandées et préventées par un administrateur système. Une fois en mémoire, ils sont épinglés là-bas et ne sont pas échangés. Le défi de l'échange d'énormes pages face à la fragmentation de la mémoire est exactement pourquoi ils restent épinglés en mémoire (lors de l'allocation d'une page énorme de 2 Mo, le noyau doit trouver 512 pages de 4 Ko contiguës de 4 Ko, qui peuvent même pas exister).
Documentation Linux sur d'énormes pages: http://lwn.net/articles/375098/
Il y a une circonstance où la fragmentation de la mémoire pourrait causer une énorme allocation de page (mais pas où des pages énormes provoquent la fragmentation de la mémoire), et c'est si votre système est configuré pour développer le pool de pages énormes si demandé par une application. Si/proc/sys/vm/nr_overcommit_hugepages est supérieur à/proc/sys/vm/nr_hugepages, cela pourrait arriver.
Il y a /proc/buddyinfo
qui est très utile. Il est plus utile avec un bon format de sortie, comme celui-ci Python Script peut faire:
https://gist.github.com/labeneator/9574294
Pour les pages énormes, vous voulez des fragments libres dans la taille 2097152 (2MIB) ou plus grand. Pour les pages énormes transparentes, elle compacte automatiquement lorsque le noyau est demandé à certains, mais si vous voulez voir combien vous pouvez obtenir, alors comme une racine courante:
echo 1 | Sudo tee /proc/sys/vm/compact_memory
Aussi oui, d'énormes pages causent de gros problèmes pour la fragmentation. Soit vous ne pouvez pas obtenir de pages énormes, soit leur présence provoque le noyau de passer beaucoup de temps supplémentaire à essayer d'en obtenir.
J'ai une solution qui fonctionne pour moi. Je l'utilise sur quelques serveurs et mon ordinateur portable. Cela fonctionne parfaitement pour les machines virtuelles.
Ajouter le kernelcore=4G
Option à votre ligne de commande de Kernel Linux. Sur mon serveur, j'utilise 8g. Soyez prudent avec le nombre, car cela empêchera votre noyau de tout attribuer à l'extérieur de cette mémoire. Les serveurs nécessitant beaucoup de tampons de socket ou que les écritures de la disquette écrit à des centaines de lecteurs ne voudront pas être limitées comme celle-ci. Toute allocation de mémoire qui doit être "épinglée" pour la dalle ou DMA est dans cette catégorie.
Toute votre autre mémoire devient alors "mobile", ce qui signifie qu'il peut être compacté dans de jolis morceaux pour une énorme allocation de page. Maintenant, les énormes pages transparentes peuvent vraiment décoller et travailler comme ils sont censés. Chaque fois que le noyau a besoin de plus de 2m de pages, il peut simplement remapper des pages de 4 km quelque part ailleurs.
Et je ne suis pas totalement sûr de savoir comment cela interagit avec Zero-Copy Direct Io. La mémoire dans la "zone mobile" n'est pas censée être épinglée, mais une demande directe IO ferait exactement que pour DMA. Cela pourrait le copier. Cela pourrait l'épingler dans la zone mobile de toute façon. Dans les deux cas, ce n'est probablement pas exactement ce que vous vouliez.