Les caches mémoire
Contents
Software version | Kernel 2.6.32+ |
---|---|
Operating System | Red Hat 6.3 Debian 7 |
Website | Kernel Website |
Last Update | 12/09/2012 |
Others |
1 L'allocation de pages
Reporter l'allocation de la mémoire lorsqu'un process le demande est bon pour les performances. A cause de localité de référence, la plupart des programmes qui demandent des allocations de mémoire de grande taille n'allouent pas celle ci d'un coup. Dans le cas d'une allocation de mémoire pour un programme, celle ci sera fera au fur et a mesure pour ne pas utiliser plus que nécessaire.
Il faut comprendre qu'il y a également une gestion des priorités en fonction de qui fait la demande. Pour l'allocation de mémoire virtuelle par exemple, lorsque le kernel fait une demande, la mémoire est allouée immédiatement, alors qu'une demande d'un utilisateur se fera petit à petit au fur et à mesure du besoin. Il y a de bonnes raisons à ces choix d'allocation. En fait beaucoup de programmes consommateurs en RAM ont des sections qui sont rarement utilisées. Il est donc inutile de tout chargé en mémoire si tout n'est pas utilisé. Cela permet de pouvoir éviter le gâchis de mémoire. Un process dont l'allocation mémoire est reportée durant la dernière minute est référencé comme étant en demande de pagination.
Il est possible de tuner un peu cette allocation pour les applications qui ont l'habitude d'allouer de gros blocks et qui libèrent cette même mémoire. Ca fonctionne également bien pour les applications qui allouent beaucoup d'un coup et quittent ensuite. Il faut jouer au niveau de sysctl :
/etc/sysctl.conf |
vm.min_free_kbytes=<value> |
Cela permet de réduite les temps de demande de pagination, la mémoire est utilisée réellement que pour ce dont elle a besoin et ça peut mettre de la pression sur la ZONE_NORMAL[1].
2 Gestion de l'overcommit
Il est avantageux pour certaines applications de laisser au kernel le droit d'allouer plus de mémoire que ce que le système peut offrir. Ceci peut être fait avec la mémoire virtuelle. En utilisant le paramètre vm.overcommit_memory dans sysctl, il est donc possible de demander au kernel d’autoriser une application à faire pleins de petites allocations :
/etc/sysctl.conf |
vm.overcommit_memory=1 |
Pour désactiver cette fonctionnalité :
/etc/sysctl.conf |
vm.overcommit_memory=0 |
Il est possible également d'utiliser la valeur 2. Celle ci permet d'overcommiter d'une taille égale à la swap + 50% de la mémoire physique. Les 50% peuvent être changé via le paramètre ratio :
/etc/sysctl.conf |
vm.overcommit_memory=2 vm.overcommit_ratio=50 |
Pour estimer la taille de la RAM qui est nécessaire pour éviter un OOM (Out Of Memory) condition pour la charge de travaille actuelle du système :
grep |
> grep -i Committed_AS /proc/meminfo Committed_AS: 3458788 kB |
Généralement l'overcommit est utile pour les application scientifiques ou créées en Fortran.
3 Slab Cache
Le Slab cache contient les pool de mémoire pré alloués par le kernel dont il va aller puiser lorsqu'il aura besoin de donner de l'espace à différents types de structures de données. A partir du moment ou ces structures de données ne mappent que des pages toutes petites ou que celles ci sont si petites que plusieurs d'entre elles entrent dans une seule page, alors il est plus efficace pour le kernel d'allouer de la mémoire pré allouée depuis l'espace mémoire Slab. Pour obtenir ces informations :
Pour avoir une vue un peu moins détaillée :
Un utilitaire existe également qui permet de monitorer en temps réel ce cache Slab, vous pouvez utiliser la commande slabtop :
Lorsqu'un process fait référence à un fichier, le kernel créer et associe un 'dentry object' pour chaque élément au niveau se son pathname. Par exemple pour /home/pmavro/.zshrc, le kernel va créer 4 'dentry objects' :
- /
- home
- pmavro
- zshrc
Chaque dentry object pointe vers l'inode associé à son fichier. Afin d'éviter à chaque utilisation de ces même paths la lecture sur disque, le kernel utilise le dentry cache ou sont stockés les dentry objects. Pour les mêmes raisons, le kernel cache également les informations sur les inodes qui sont donc contenu dans le slab.
4 Le cache ARP
Beaucoup de problèmes de performances réseaux peuvent être due au cache ARP étant trop faible. Par défaut, celui ci est limité à 512 entrées soft et 1024 hard au niveau des Ulimits. La limite soft devient une limite hard après 5 secondes. Lorsque cette limite est dépassée, le kernel fait un garbage collector et scan le cache pour purger les entrées pour rester en dessous de cette limite. Ce garbage collector peut également entrainer une suppression complète du cache. Admettons que votre cache est limité à 1 entrée dans le cache mais vous vous connectez depuis 2 machines distantes. Chaque packets entrant et sortant vont causer un garbage collector et une réinsertion dans le cache ARP. Il y aura donc un changement permanent dans le cache. Pour vous donner une idée de ce qui peut se passer sur un système :
Pour voir les entrées ARP qui mappent les adresses matériels vers les adresses des protocoles :
grep |
> grep -i arp /proc/slabinfo arp_cache 4 8 448 8 1 : tunables 54 27 8 : slabdata 1 1 0 |
Trop d'entrées ARP dans le cache mettent la pression sur la ZONE_NORMAL. Pour lister les entrées ARP, il existe 2 solution :
ip |
> ip neighbor list 10.101.0.254 dev eth0 lladdr 00:25:45:db:71:57 REACHABLE |
ou
cat |
> cat /proc/net/arp IP address HW type Flags HW address Mask Device 10.101.0.254 0x1 0x2 00:25:45:db:71:57 * eth0 |
Pour vider le cache ARP :
ip |
ip neighbor flush dev eth0 |
Il est possible de faire quelques réglages du cache ARP en spécifiant la limite soft, hard et la fréquence à laquelle le garbage collector doit être exécuté (en secondes) :
/etc/sysctl.conf |
net.ipv4.neigh.default.gc_thresh2=<soft_value> net.ipv4.neigh.default.gc_thresh3=<hard_value> net.ipv4.neigh.default.gc_interval=<gc_intrval_value> |
Il existe également une autre option qui permet de régler le temps minimum des jiffies en espace utilisateur, vers les entrées en cache. Il y a 100 jiffies en espace utilisateur en 1 seconde :
/etc/sysctl.conf |
net.ipv4.neigh.default.locktime=<value> |
5 Les pages cache
Un très grand pourcentage de l'activité de pagination est due aux IO. Pour la lecture depuis le disque vers la mémoire par exemple, ça forme des pages cache. Voici les cas de vérification du page cache pour les requêtes IO :
- Lecture et écriture de fichiers
- Lecture et écriture via des fichiers de type block device
- Les accès à des fichiers mappés en mémoire
- Les accès qui swappent des pages
- La lecture de dossiers
Pour voir les allocations du page cache, il suffit de regarder les buffers caches :
grep |
> grep -i buffer /proc/meminfo Buffers: 225624 kB |
Il est possible de tuner la taille mémoire des pages cache :
/etc/sysctl.conf |
vm.lowmem_reserve_ratio=<value> vm.vfs_cache_presure=<value> |
Et il est également possible de tuner le taux d'arrivée :
/etc/sysctl.conf |
vm.page-cluster=<value> vm.zone_reclaim_mode=<value> |
6 Les pages Anonymes
Sous Linux, seulement certains types de pages sont swappées. Il n'y a pas besoin de swapper des programmes de type texte du fait qu'ils existent déjà sur le disque. Également, pour la mémoire qui a été utilisée pour stocker le fichier dont le contenu a été modifié, le kernel va prendre les devants et écrire les données sur le fichier auquel il appartient vers le swap. Seules les pages qui n'ont pas d'association avec un fichier sont écrites en swap.
Le cache swap est utilisé pour garder une trace des pages qui ont été précédemment sorties du swap et qui n'ont pas été reswappées depuis. Si le kernel swap les threads qui ont besoin de swapper une page plus tard, si il trouve une entrée pour cette page en cache swap, il est possible de swapper sans avoir à l'écrire sur le disque.
Le fichier de chaque PID statm permet de voir les pages anonymes (ici PID 1) :
> cat /proc/1/statm 2659 209 174 9 0 81 0 |
- 2659 : total program size
- 209 : resident set size (RSS)
- 174 : shared pages (from shared mappings)
- 9 : text (code)
- 81 : data + stack
Ceci contient donc la RSS et la mémoire partagée utilisé par un process. Mais en fait le RSS que fournit le kernel est constitué les pages anonymes et partagées, d'où :
- Pages anonymes = RSS - Partagée
7 SysV IPC
Une autre chose qui consomme de la mémoire est la mémoire pour les communications IPC.
Les Semaphores autorisent 2 ou plusieurs process pour coordonner les accès aux ressources partagées.
Les Message Queues autorisent les process à se coordonner pour les échanges de message. Les régions de Shared memory autorisent les process à communiquer en lisant et écrivant aux mêmes régions mémoire.
Un process peut souhaiter utiliser un de ces mécanismes mais doit créer des appels systèmes appropriés pour aller les ressources souhaitées.
Il est possible de mettre des limites à ces IPC sur systèmes SYSV. Pour voir la liste actuelle :
L'utilisation du /dev/shm peut être une solution pour réduire considérablement le temps de service de certaines applications. Attention toute fois à utiliser ce système comme espace de stockage temporaire du fait qu'il soit en mémoire. Il existe également une commande 'ipcrm' pour forcer la suppression des segments partagés en mémoire. Mais dans l'absolu, vous n'aurez jamais à utiliser cette commande.
Il est possible de tuner ces valeurs (présentes dans /proc/sys/kernel) via les sysctl :
cat |
> cat sem 250 32000 32 128 |
- 250 : nombre maximum de sémaphores par tableaux de sémaphores
- 32000 : nombre maximum de sémaphores allouées côté système
- 32 : nombre maximum d'opérations allouées par appels systèmes de sémaphore
- 128 : nombre de tableaux de sémaphore
Si vous souhaitez les modifier :
/etc/sysctl.conf |
kernel.sem = 250 256000 32 1024 |
Il y a d'autres paramètres intéressants (avec leurs valeurs par défaut) :
Pour plus d'informations consultez le man 5 de proc.
8 Obtenir les informations mémoire
Il existe plusieurs solutions pour récupérer les tailles des mémoires. La plus connue d'entre elles est la commande free :
free |
> free -ltm total used free shared buffers cached Mem: 3801 3520 281 0 224 1822 Low: 3801 3520 281 High: 0 0 0 -/+ buffers/cache: 1473 2328 Swap: 3811 4 3807 Total: 7613 3524 4089 |
Vous pouvez aussi récupérer les informations dans dmesg. Nous l'avons vu également plus haut, il est possible de récupérer dans meminfo la taille totale de l’espace virtuelle :
grep |
> grep -i vmalloc /proc/meminfo VmallocTotal: 34359738367 kB VmallocUsed: 560128 kB VmallocChunk: 34359113168 kB |
Pour voir la plus grosse taille de chunk libre :
grep |
> grep -i chunk /proc/meminfo VmallocChunk: 34359113168 kB |
Pour les pages table :
Pour les allocations IO, il existe iomem :