PostgreSQL, Linux, HugePage

De Linux France
Aller à : navigation, rechercher

Introduction

Objectif: paramétrer/configurer PostgreSQL (ici version 13) sous Linux de sorte qu'il emploie des HugePages.

Documentation pertinente

Avertissement

Attention: bricoler au hasard un paramètre noyau peut mettre en péril un processus voire le noyau.

Allouer beaucoup de HugePages n'est pas nécessairement souhaitable car elles ne sont pas utilisées par le buffercache (il faut donc les utiliser de façon plus rentable que le ferait ce dernier), ne sont pas swapables (il faut donc les employer de sorte que ce qu'elles cachent est plus intensément utilisé que quelque contenu de fichier non ainsi caché que ce soit), et il me semble que KSM les néglige. En résumé si le serveur est réservé à PostgreSQL cela fait sens, sinon mieux vaut analyser. Sur un serveur animant des VMs il semble qu'instaurer Transparent Hugepage est plus efficace(?).

Approche

Au préalable déterminer si un autre logiciel emploie des HugePages. Pour cela invoquer:

grep -i HugePages_Total: /proc/meminfo

Qui doit retourner "HugePages_Total: 0".

Nous paramétrerons le noyau (kernel) ainsi que PostgreSQL ("PG").

L'utilitaire sysctl communique au noyau des paramètres, ce dernier les applique immédiatement. Nous les consignerons dans un fichier de configuration

Le contenu de ce fichier est textuel, en voici un exemple établissant la valeur du paramètre "toto" à 7 et celle de "titi" à 42 (les noms de ces paramètres sont fictifs, ne PAS les employer!) :

toto = 7
titi = 42

Pour modifier immédiatement les valeurs de ces paramètres du noyau actif invoquer en tant que root "sysctl -p fichier", où fichier est le nom d'un fichier. Durant la mise au point placer ce fichier hors du répertoire /etc
Exemple:

sysctl -p ~/postgres.conf

Paramétrer le kernel

Les premiers paramètres noyau pertinents sont kernel.shmmax et kernel.shmall.

J'opte tout d'abord pour un paramétrage maximaliste, révélé par ce script qui livre des valeurs établies en considérant que les tampons de PostgreSQL utiliseront 99% de la RAM:

#!/bin/bash
page_size=$(getconf PAGE_SIZE)
phys_pages=$(getconf _PHYS_PAGES)
shmall=$(( phys_pages * 99 / 100 ))
echo kernel.shmmax = $(( shmall * page_size ))
echo kernel.shmall = $shmall

Invoquer ce script sur la machine où PG fonctionnera afin d'obtenir les valeurs des paramètres noyau kernel.shmmax et kernel.shmall', puis les placer dans le fichier destiné à sysctl.

C'est absurdement trop élevé et uniquement destiné à nous permettre de négliger la quantité de mémoire partagée nécessaire à PG, afin de nous concentrer sur le calcul du nombre de HugePages.

Déclarer ainsi, via le paramètre vm.hugetlb_shm_group l'identificateur numérique du groupe (GID) autorisé à employer des HugePages.

J'ai pour cela créé un groupe (GID 1001) dont j'ai rendu le compte "postgres" membre.

Résultat sur ma machine:

kernel.shmmax = 200714948608
kernel.shmall = 49002673
vm.hugetlb_shm_group=1001

Paramétrer PostgreSQL

Paramétrer votre instance de PG.

"huge_pages = on" est nécessaire.

"shared_buffers" est nécessaire, ce tampon sera alloué dans des HugePages.

"work_mem", "maintenance_work_mem" et "max_connections" ont un impact non négligeable sur le volume total de mémoire centrale que PG demandera durant son démarrage.

Déterminer le nombre de HugePages nécessaires à PG

Démarrer votre instance de PostgreSQL.

Si elle a pu démarrer vous n'avez probablement pas besoin de ce document, sauf peut-être afin d'ajuster la quantité de HugePages de sorte qu'aucune ne soit inutilisée.

Si elle n'a pu démarrer lire son fichier de traces (sous Debian il se trouve dans "/var/log/postgresql/"). Il recèle un message révélant la quantité de mémoire centrale dont PG réclama en vain l'allocation. Exemple:

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 164914520064 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

C'est ici "164914520064 bytes", quantité minimale d'octets dont nous avons besoin en mémoire partagée dans des HugePages disponibles.

C'est la valeur minimale à associer au paramètre kernel.shmmax.

Il faut ensuite obtenir la taille de chaque HugePage:

grep -i Hugepagesize /proc/meminfo

Le plus souvent elle vaut 2048 kB, donc deux mégaoctets.

Diviser la quantité de mémoire requise par PG (en octets) par cette taille (en octets). Attention: 1 kB contient 1024 octets, donc 2048 kB contiennent (1024*2048) octets.

Le logiciel bc peut calculer cela:

echo -e "scale=1\n164914520064/(1024*2048)"|bc

Arrondir à l'entier supérieur puis utiliser le résultat en tant que paramètre du noyau vm.nr_hugepages.

Contenu possible du fichier des paramètres du noyau:

# http://wiki.linux-france.org/wiki/PostgreSQL,_Linux,_HugePage
kernel.shmmax = 164914520064
kernel.shmall = 41652272
vm.nr_hugepages=78638
vm.hugetlb_shm_group=1001
vm.overcommit_memory=2
vm.overcommit_ratio=70
vm.swappiness = 100
# une fraction du débit (octets/seconde) de la mémoire de masse
vm.dirty_background_bytes=62914560
# 100 fois plus
vm.dirty_bytes=6291456000

Établir les paramètres du noyau actif en invoquant "sysctl -p NomDuFichier" (plusieurs minutes seront vraisemblablement nécessaires si le noyau doit réorganiser la mémoire, patienter tant que le processus de "sysctl" est actif).

Tenter de démarrer PG. Si cela échoue encore augmenter progressivement cette valeur.

Optimiser

Lorsque PG démarrera vérifier la quantité de HugePages qu'il réclame:

grep -i huge /proc/meminfo

Idéalement toutes les HugePages disponibles sont allouées, donc le paramètre noyau vm.nr_hugepages est optimal.

AnonHugePages:      4096 kB
ShmemHugePages:        0 kB
HugePages_Total:   78638
HugePages_Free:    76983
HugePages_Rsvd:    76983
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:        161050624 kB

Utiliser PG. Après un moment il emploie ces HugePages:

AnonHugePages:     12288 kB
ShmemHugePages:        0 kB
HugePages_Total:   78638
HugePages_Free:       94
HugePages_Rsvd:       94
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:        161050624 kB

Établir cette configuration

Placer le fichier de déclaration de ces paramètres du noyau de sorte qu'ils soient restaurés durant chaque amorçage. Sous Debian les placer par exemple dans un nouveau fichier nommé "/etc/sysctl.d/postgres.conf" qui est ici:

# http://wiki.linux-france.org/wiki/PostgreSQL,_Linux,_HugePage
kernel.shmmax = 164914520064
kernel.shmall = 41652272
vm.nr_hugepages=78638
vm.hugetlb_shm_group=1001

Autres paramètres potentiellement adéquats sur une machine réservée à PG:

vm.overcommit_memory=2
vm.overcommit_ratio=70
vm.swappiness = 100
# une fraction du débit (octets/seconde) de la mémoire de masse
vm.dirty_background_bytes=62914560
# 100 fois plus
vm.dirty_bytes=6291456000