Existe-t-il un moyen de détecter la fragmentation de la mémoire sur Linux? En effet, sur certains serveurs de longue durée, j'ai remarqué une dégradation des performances et ce n'est qu'après avoir redémarré le processus que je constate de meilleures performances. Je l'ai remarqué davantage lors de l'utilisation de la prise en charge des pages énormes Linux - les pages énormes dans Linux sont-elles plus sujettes à la fragmentation?
J'ai regardé / proc / buddyinfo en particulier. Je veux savoir s'il existe de meilleures façons (pas seulement les commandes CLI en soi, n'importe quel programme ou contexte théorique) de le regarder.
linux
linux-kernel
Raghu
la source
la source
vmstat
sur le terrainso
?vmstat
est une expérience utilisateur courante. Si vous écriviez un programme pour faire de même, ce serait différent. Si vous avez l'intention d'utiliser bash pour récolter ces informations, modifiez votre question, elle ne sera pas fermée :)Réponses:
Je réponds à la balise linux . Ma réponse n'est spécifique qu'à Linux .
Oui, les pages énormes sont plus sujettes à la fragmentation. Il existe deux vues de la mémoire, celle que votre processus obtient (virtuelle) et celle que le noyau gère (réelle). Plus une page est grande, plus il sera difficile de regrouper (et de la conserver) ses voisins, en particulier lorsque votre service s'exécute sur un système qui doit également prendre en charge d'autres qui, par défaut, allouent et écrivent sur beaucoup plus de mémoire qu'eux finissent par utiliser.
Le mappage par le noyau des adresses accordées (réelles) est privé. Il y a une très bonne raison pour laquelle l'espace utilisateur les voit comme le noyau les présente, car le noyau doit pouvoir surcharger sans confondre l'espace utilisateur. Votre processus obtient une belle, contigu « Disneyfied » espace d'adressage où travailler, sans se soucier de ce que le noyau est en fait en train de faire avec cette mémoire dans les coulisses.
La raison pour laquelle vous constatez une dégradation des performances sur des serveurs de longue durée est probablement due au fait que les blocs alloués qui n'ont pas été explicitement verrouillés (par exemple
mlock()
/mlockall()
ouposix_madvise()
) et non modifiés depuis un certain temps ont été paginés , ce qui signifie que votre service dérape sur le disque lorsqu'il doit lire leur. La modification de ce comportement fait de votre processus un mauvais voisin , c'est pourquoi de nombreuses personnes placent leur SGBDR sur un serveur complètement différent de web / php / python / ruby / que ce soit. La seule façon d'y remédier, sainement, est de réduire la concurrence pour les blocs contigus.La fragmentation n'est vraiment perceptible (dans la plupart des cas) que lorsque la page A est en mémoire et que la page B a été déplacée pour être échangée. Naturellement, le redémarrage de votre service semble `` remédier '' à cela, mais uniquement parce que le noyau n'a pas encore eu l'occasion de consulter le processus '' (maintenant) les blocs nouvellement alloués dans les limites de son ratio de surcharge.
En fait, le redémarrage (disons) de 'apache' sous une charge élevée va probablement envoyer des blocs appartenant à d'autres services directement sur le disque. Alors oui, 'apache' s'améliorerait pendant un court laps de temps, mais 'mysql' pourrait souffrir .. au moins jusqu'à ce que le noyau les fasse souffrir également quand il y a simplement un manque de mémoire physique suffisante.
Ajoutez plus de mémoire ou divisez les
malloc()
consommateurs exigeants :) Ce n'est pas seulement la fragmentation que vous devez regarder.Essayez
vmstat
d'obtenir un aperçu de ce qui est réellement stocké où.la source
Noyau
Pour obtenir l'utilisation actuelle de l'index de fragmentation:
Pour défragmenter la mémoire du noyau, essayez d'exécuter:
Vous essayez également de désactiver Transparent Huge Pages (aka THP) et / ou de désactiver le swap (ou de le diminuer
swappiness
).Espace utilisateur
Pour réduire la fragmentation de l'espace utilisateur, vous voudrez peut-être essayer différents allocateurs, par exemple
jemalloc
(il a de grandes capacités d'introspection , qui vous donneront un aperçu de la fragmentation interne de l'allocateur).Vous pouvez passer à malloc personnalisé en recompilant votre programme avec lui ou tout simplement en exécutant votre programme avec
LD_PRELOAD
:LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app
(méfiez-vous des interactions entre THP et les allocateurs de mémoire )Bien que légèrement sans rapport avec la fragmentation de la mémoire (mais connecté au compactage / migration de la mémoire), vous souhaiterez probablement exécuter plusieurs instances de votre service, une pour chaque nœud NUMA et les lier à l'aide
numactl
.la source
mmap
) sont également implémentés différemment sur différents noyaux (par exemple Linux vs FreeBSD), ou même sur différentes versions du même système d'exploitation (2.6.32 vs 3.2 vs 3.10) .. "il autorise les pages modifiées [. ..] à éjecter de la [...] mémoire physique "- qui masquera les fuites de mémoire. "gérer les cas où beaucoup plus de mémoire est réservée que celle utilisée" - un système lent est bien pire qu'un système en panne, donc "sain" est discutable.L'utilisation de pages volumineuses ne devrait pas entraîner de fragmentation supplémentaire de la mémoire sous Linux; Le support Linux pour les pages volumineuses est uniquement pour la mémoire partagée (via shmget ou mmap), et toutes les pages volumineuses utilisées doivent être spécifiquement demandées et préallouées par un administrateur système. Une fois en mémoire, ils y sont épinglés et ne sont pas échangés. Le défi de l'échange de pages énormes face à la fragmentation de la mémoire est exactement la raison pour laquelle elles restent épinglées en mémoire (lors de l'allocation d'une énorme page de 2 Mo, le noyau doit trouver 512 pages 4KB libres contiguës, qui n'existent peut-être même pas).
Documentation Linux sur d'énormes pages: http://lwn.net/Articles/375098/
Il existe une circonstance où la fragmentation de la mémoire peut ralentir l'allocation de pages volumineuses (mais pas là où les pages volumineuses provoquent la fragmentation de la mémoire), et c'est si votre système est configuré pour augmenter le pool de pages volumineuses à la demande d'une application. Si / proc / sys / vm / nr_overcommit_hugepages est supérieur à / proc / sys / vm / nr_hugepages, cela peut se produire.
la source
Il y en a
/proc/buddyinfo
qui est très utile. C'est plus utile avec un bon format de sortie, comme ce script Python peut le faire:https://gist.github.com/labeneator/9574294
Pour les pages volumineuses, vous voulez des fragments gratuits au format 2097152 (2 Mo) ou plus. Pour les pages volumineuses transparentes, il se compactera automatiquement lorsque le noyau en sera demandé, mais si vous voulez voir combien vous pouvez en obtenir, alors en tant que root:
De plus, les pages énormes causent de gros problèmes de fragmentation. Soit vous ne pouvez pas obtenir de pages volumineuses, soit leur présence oblige le noyau à 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 très bien pour les machines virtuelles.
Ajoutez l'
kernelcore=4G
option à votre ligne de commande du noyau Linux. Sur mon serveur, j'utilise la 8G. Soyez prudent avec le nombre, car cela empêchera votre noyau d'allouer quoi que ce soit en dehors de cette mémoire. Les serveurs qui ont besoin de beaucoup de tampons de socket ou qui écrivent des disques sur des centaines de lecteurs n'aimeront pas être limités comme ça. Toute allocation de mémoire qui doit être «épinglée» pour la dalle ou le DMA appartient à cette catégorie.Toute votre autre mémoire devient alors "mobile", ce qui signifie qu'elle peut être compactée en jolis morceaux pour une allocation de page énorme. Désormais, les pages immenses et transparentes peuvent vraiment décoller et fonctionner comme elles sont censées le faire. Chaque fois que le noyau a besoin de plus de 2 millions de pages, il peut simplement remapper des pages 4K à un autre endroit.
Et, je ne suis pas totalement sûr de la façon dont cela interagit avec les E / S directes sans copie. La mémoire dans la "zone mobile" n'est pas censée être épinglée, mais une demande d'E / S directe ferait exactement cela pour le DMA. Il pourrait le copier. Il pourrait de toute façon le coincer dans la zone mobile. Dans les deux cas, ce n'est probablement pas exactement ce que vous vouliez.
la source