Ai-je assez de mémoire et de swap sur ma machine Solaris ?

Définitions, concepts et autres joyeusetés

Périphérique de Swap

Egalement appelé disque de swap ou swap tout court, un périphérique de swap (swap device) est un espace de stockage brut confié aux bons soins du kernel pour y stocker, éventuellement, ceraines pages mémoires pour le cas où cette ressource se faisait rare. Il fût un temps, que certains ne peuvent pas connaître mais qui en ont tout de même entendu parler, où l’on définissait le volume de cet espace par rapport à la taille de la mémoire physique (RAM). Depuis une petite décennie, on a tous dit que c’était bien fini, même des fois on en rit. Vous découvrirez un peu plus bas que finalement cet espace n’est pas si inutile que ça.

Mémoire Physique

Non, ce n’est pas une insulte, c’est juste l’espace mémoire auquel le kernel accède au travers de ses contrôleurs mémoires, bus, MMU, etc. Bref, en règle générale ça se matérialise sous forme de barrettes, et surtout c’est là qu’est chargé tout ce dont vos process ont besoin pour travailler; dès que vous demandez la lecture d’un fichier par exemple, une page du fichier est chargé en mémoire (voire plus avec les phénomènes de cache), et les octets demandés vous sont renvoyés. Ceci est vrai évidemment pour les fichiers exécutables; pour les faire tourner, le code doit également être chargé en mémoire. En résumé, chaque fourmi besogneuse de la machine va utiliser cet espace.

Freelist

La freelist est la quantité effective de mémoire physique disponible à un instant. Lorsqu’un process demande l’allocation d’une zone mémoire, cette zone est réservée Lorsqu’une page de cette mémoire n’est plus utilisé (par exemple vous avez fermé le fichier ou encore votre process est décédé -RIP- ), le kernel va la tagguer comme disponible pour un utilisation ultérieure. L’ensemble de la mémoire non utilisé ou plus utilisé constitue la freelist.

Mémoire Virtuelle

Aussi connu sous le nom de VM ou carrément de Swap, la Mémoire Virtuelle est un agrégat de tout ce qui est alouable, que ce soit en RAM ou sur disque. La VM brute correspond donc à RAM + SWAP-DEVICE. A cette VM brute il faut soustraire quelques Mo par-ci, par là pour comprendre à quel chiffre les commandes comme swap -s ou vmstat se réfèrent. En fait, la formule magique pour calculer la VM sur Solaris est RAM + SWAP-DEVICE - (OBP + HyperViseur + Non_Swappable_Kernel_Pages)

Page-out, Swap-out

Si quelqu’un a besoin de s’allouer de l’espace et que la freelist est insuffisante, le kernel va tenter de libérer des pages :

  • Eléments anciens des caches filesystem
  • Pages de fichier non utilisées depuis un certain temps
  • Process en attente depuis un certain temps

Pour libérer ces espaces, soit on peut resynchroniser avec un espace disque déjà alloué (cas des fichiers par exemple), soit l’existence des données est purement mémoire (cas d’une partie de la zone utilisée par les process). Dans ce dernier cas, le kernel va utiliser les périphériques de swap pour sortir ces pages de la mémoire physique (page-out). Un process dont les éléments vitaux sont évacuées sur le périphérique de swap est dit /swappé (swap-out).

Intimate Shared Memory (ISM)

L’un des procédés de communication inter-processus défini par System V (ipcs) est le partage de zone mémoire. Ce procédé a été optimisé dans Solaris, à l’attention notamment des éditeurs de SGBDR. Les segments d’ISM, contrairement aux shared-mem classiques (shm), sont verrouillées à la création. Les avantages de ce verrouillage :

  • Les pages se trouvent toujours en RAM, quoiqu’il se passe sur la machine
  • Le kernel se permet l’utilisation d’un mécanisme de verrouillage rapide lors des opérations de lecture/écriture de ces segments, économisant ainsi de nombreux cycles CPU.
  • Les structures kernel de translations d’adresses (physique↔virtuel) mémoire sont partagées avec les process, ce qui permet une économie de consommation mémoire et également de cycles CPUs.
  • Sur architecture Sparc, les pages réservées sont automatiquement allouées en large page, permettant une économie de pointeurs (jusqu’à un facteur 512) et par voie de conséquence une augmentation notable des performances sur les systèmes hébergeant une quantité importante de RAM.

Dynamic ISM (DISM)

L’ISM a les inconvénients de l’un de ses avantages : son verrouillage permanent interdit tout redimensionnement, obligeant les applications à s’arrêter et redémarrer lorsqu’elle souhaite augmenter la taille de leur segment de mémoire partagée (SGA Oracle par exemple), et interdisant toute velléité de retrait à chaud d’une carte système sur laquelle ces segments seraient installés (DR -Dynamic Reconfiguration- des systèmes SunFire et autre Mx000 qui permettent d’arrêter et de retirer à chaud une carte système -System Board- même si nécessaire en déplaçant le kernel -et ça il n’y a que Solaris qui sait le faire avec sa fameuse quiescence-).

La DISM répond à ces besoins en permettant :

  • à l’application de ne verrouiller que certaines parties de ses segments (mlock()), d’en déverrouiller, d’augmenter ou diminuer la taille desdits segments.
  • au kernel de déplacer les segments si nécessaire (notamment temporairement vers un périphérique de swap pour permettre la DR).

Mémoire réservée versus Mémoire allouée

Une demande d’allocation de mémoire (que ce soit un mmap() ou un malloc() qui fait appel à brk() ) ne va pas immédiatement faire diminuer la freelist.

Le kernel va diminuer l’espace disponible de la VM, en incrémentant l’espace réservé.

Ce n’est que lorsqu’une page est réellement modifiée, que la taille de cette page va changer de compteur...de réservé, elle va passer dans le camp de alloué; et si elle est alloué, elle vient forcément diminuer la freelist.

On voit déjà que le fameux périphérique de swap n’est pas si anodin qu’il n’y parait, puisque lorsque je fait une demande d’allocation de mémoire, cette allocation tape dans la VM de façon indifférencié. Ce n’est qu’à l’utilisation réelle de cette zone que la différence RAM versus SWAP-DEV va jouer.

Pour donner un exemple plus précis et assez contemporain, si vous lancez 20 machines Java avec l’option -Xms256m, chacune de ces machines va faire une demande d’allocation de 256 Mo, soit au total une demande de 5 Go de ressource. Supposons que le code que vous activez via ces machines Java sont des serveurs qui se mettent en attente d’activation distante. Tant que personne ne les activent réellement, on peut raisonnablement penser que l’utilisation réelle des 5 Go est de quelques centaines de Mo. Si vous avez de l’espace disponible dans votre périphérique de swap, le fait que ces serveurs soient lancés, mais pas actifs, ne pénalisent personne. Dans le cas inverse, ces serveurs inactifs consomment réellement 5 Go.

VM consommée par la DISM

  • Lorsqu’une application demande l’allocation de segments de DISM, tout naturellement on vient incrémenter le compteur de mémoire réservée.
  • Comme expliqué au paragraphe précédent, une modification des pages entraîne une modification des compteurs alloué versus réservé. Il en est de même sur un ordre de verrouillage par mlock().
  • Lors d’un verrouillage, un autre compteur est touché : celui de la VM elle-même. Le kernel voulant se conserver la capacité de déplacer ces segments quelque-soit les conditions environnementales, il procède à cette amputation. Ceci signifie que de la DISM verrouillé a un double impact sur la VM; un premier lors de la demande d’allocation, un deuxième lors de la demande de verrouillage. Si vous avez de l’espace disponible sur le périphérique de swap, cela conduit indirectement à une réservation en RAM et une réservation sur le périphérique. Dans le cas contraire, cela conduit à une double amputation en RAM.

Quel espace disque faut-il affecter au swap ?

Oui, je sais. Il n’est nullement obligatoire d’affecter un espace disque de swap pour démarrer une machine Solaris. Je sais également qu’une machine qui commence à swaper sur disque des process est à priori en très mauvaise posture.

Mais j’ose imaginer qu’après avoir lu les paragraphes précédent, vous serez d’accord avec moi pour dire que ce serait dommage, voire idiot.

Utilisation de containers ou de gestion de ressources sur les projets

Que ce soit sur un projet ou sur un container, l’utilisation de capping mémoire va entraîner de l’extraction de la RAM de certaines ressources peu utilisées, et ceci avant même que la machine ne soit désespérée. Ceci dépend des attributs de limitation (de capping) et de la configuration de rcapd.

Pour la faire court, le capping mémoire va permettre d’anticiper la crise en libérant doucement ce qui n’est effectivement que peu utilisé, mais il risque pour cela d’avoir besoin d’espace de swap sur disque.

Difficile néanmoins d’établir une formule de calcul...ce n’est ici qu’une justification supplémentaire au fait de provisionner de l’espace de swap sur disque.

Espace dédié à la DISM

Prenez en compte l’application qui utilise de la DISM va forcément verrouiller au moins une partie de cette mémoire partagée. Il est difficile de prévoir le taux de verrouillage effectif, il est donc raisonnable d’octroyer sur disque un espace égal à l’utilisation de DISM qui sera faite. Pensez également qu’il est fort possible que l’administrateur de l’application en question (en général une SGBDR) augmente au fil du temps la taille de cette zone, prévoyez donc un peu de marge.

Réservation de mémoire sans utilisation

Cette fois il faut prendre en compte le type d’utilisation de la machine.

Une machine de production sera, à priori, peut enclin à héberger des processus réservant de la mémoire sans l’utiliser. On ignorera sans doute ce point.

Une machine de qualification ou de recette sera plus sensible à ce genre de fluctuations, au delta près de la manière dont elle sera gérée : est-ce qu’elle est mise à disposition d’une seule équipe, d’un seul projet à un instant T, ou partagée entre plusieurs projets qui n’y travaille pas forcément en simultané pure ? La règle ici serait de provisionner un espace correct permettant à des process de faire ce type de réservation, sans utilisation effective, sans déranger.

Sauvegarde du crash-dump

Je ne pourrais que trop vous conseiller en environnement critique de dédier un périphérique particulier pour faire cet office; si vous ne pouvez/voulez pas, prévoyez que votre espace disque soit d’au moins 50% votre RAM.

Alors ! Combien ?

Cela n’engage que moi, mais voici quelques conseils qui pourront vous aide à prendre votre propre décision en fonction de votre environnement.

  • Sur une machine de développement, prévoir au minimum ( taille_de_la_RAM + taille_des_DISM )
  • Sur une machine de production, prévoir au minimum ( 0,5 * taille_de_la_RAM + 1,2 * taille_des_DISM )
  • Dans tous les cas, ne jamais descendre en dessous de ( 0,5 * taille_de_la_RAM )

Outils

  • Déterminer la RAM réservée
# swap -s
total: 16620016k bytes allocated + 8178424k reserved = 24798440k used, 14190768k available
  • Déterminer la taille de la freelist
# vmstat 2 2
 kthr      memory            page            disk          faults      cpu
 r b w   swap  free  re  mf pi po fr de sr m1 m1 m1 m2   in   sy   cs us sy id
 0 0 0 9377880 7663624 564 3252 1023 1 1 0 0 15 8 8  1 2845 12258 6980 4  7 89
 0 0 0 14162568 2507560 0 27 0  0  0  0  0  0  0  0  0  810 4752 5463  3  4 94
  • Déterminer les segments d’ISM/DISM

C’est la colonne ISMATTCH de la commande ipcs -Zbim ou ipcs -ZAm qui vous donne le nombre d’attachement en mode ISM du segment (SHM_SHARE_MMU ou SHM_PAGEABLE).

# ipcs -Zim
IPC status from <running system> as of Wed Mar 11 17:34:56 CET 2009
T         ID      KEY        MODE        OWNER    GROUP ISMATTCH     ZONE
Shared Memory:
m   33554529   0x41008e6b --rw-rw-rw- webservd webservd        0    zweb
m  251658331   0x4100800e --rw-rw-rw-     root     root        0    zweb
m  251658330   0x41008cc2 --rw-rw-rw-     root     root        0    zweb
m 1711276098   0x741cc1a4 --rw-rw-rw-     root     root        0   zoracle
m  117440577   0x741cc1a3 --rw-rw-rw-     root     root        0   zoracle
m  117440576   0x741cc1a2 --rw-rw-rw-     root     root        0   zoracle
m  234881087   0x741cc1a1 --rw-rw-rw-     root     root        0   zoracle
m 2113929278   0x741cc1a0 --rw-rw-rw-     root     root        0   zoracle
m  218103860   0x1483b388 --rw-rw----   orause olalalala       9   zoracle
m  201326685   0xbd45e16c --rw-rw----   orause olalalala      12   zoracle
m 2046820397   0x7faa22a8 --rw-rw----   orause olalalala      13   zoracle
m 1358954511   0x900fbad4 --rw-rw----   orause olalalala      11   zoracle
m 1526726667   0xc9ff9a44 --rw-rw----   orause olalalala      11   zoracle
m  184549379   0x2da62e70 --rw-rw----   orause olalalala      10   zoracle
m  318767105   0x67960de0 --rw-rw----   orause olalalala      10   zoracle

Pour calculer la taille totale de ce type de segment :

# ipcs -ZAm | awk 'NR>1&&$16>0{s+=$10} END{print "total=", s/1024}'
total= 10149912
  • Avoir un aperçu de l’utilisation globale de la mémoire

Ca peut être long, pas de panique !

# echo "::memstat" | mdb -k
Page Summary                Pages                MB  %Tot
------------     ----------------  ----------------  ----
Kernel                     974712              7614   29%
Anon                      2012652             15723   59%
Exec and libs               16454               128    0%
Page cache                  37295               291    1%
Free (cachelist)            74369               581    2%
Free (freelist)            271852              2123    8%

Total                     3387334             26463
Physical                  3332228             26033

Références

Remerciements

Le support de Sun France qui m’a longuement aidé à mettre tous ces éléments ensembles (et spéciale dédicace à François !).







Nicolas Dorfsman Mars 2009

 
docs/base/memoire.txt · Dernière modification: 14/03/2009 09:49