Numastat
| Fiche express | |
|---|---|
| Domaine | Mémoire, NUMA, serveurs multi-socket |
| Commande | numastat
|
| Paquet | numactl (RHEL/Debian/Ubuntu)
|
| Contexte | Serveurs multi-processeurs (NUMA) — bases de données, JVM, virtualisation |
| Voir aussi | numactl --hardware (topologie), Vmstat, Mémoire
|
numastat affiche des statistiques d'allocation mémoire par nœud NUMA (Non-Uniform Memory Access). Sur un serveur multi-socket, chaque processeur physique possède sa propre mémoire locale : accéder à cette mémoire locale est rapide, mais accéder à la mémoire rattachée à un autre socket (mémoire distante) traverse une interconnexion (QPI/UPI chez Intel, Infinity Fabric chez AMD) et coûte davantage en latence et en bande passante. numastat permet de repérer ce genre de déséquilibre, souvent responsable de dégradations de performance difficiles à diagnostiquer autrement.
Pourquoi NUMA compte
Sur une architecture NUMA, le noyau Linux essaie par défaut de placer la mémoire d'un process sur le nœud NUMA le plus proche du CPU qui l'exécute (politique "local"), mais ce n'est pas toujours possible : mémoire locale déjà saturée, process qui migre d'un CPU à l'autre, ou allocation faite avant que l'ordonnanceur ne fixe le process sur un nœud. Le symptôme typique est un process qui tourne sur les CPU du nœud 0 mais dont la mémoire est majoritairement allouée sur le nœud 1 : chaque accès mémoire traverse alors l'interconnexion inter-socket, avec une latence nettement supérieure à un accès local. C'est un sujet de tuning classique pour les bases de données (MySQL/MariaDB, PostgreSQL) et les JVM (Java) qui allouent de gros segments de mémoire (buffer pool, heap) : un mauvais placement NUMA peut coûter plusieurs pourcents de performance, voire beaucoup plus sous forte charge.
Utilisation de base
numastat # hits/misses NUMA par nœud, pour tous les process
Colonnes affichées par défaut :
- numa_hit — allocations mémoire faites sur le nœud prévu (comportement souhaité, le plus fréquent)
- numa_miss — allocations faites sur ce nœud alors qu'un autre nœud était visé (indique de la pression mémoire ou un mauvais placement)
- numa_foreign — allocations initialement prévues pour ce nœud mais redirigées vers un autre
- interleave_hit — allocations réussies en mode interleave (répartition volontaire sur tous les nœuds)
- local_node — mémoire allouée par un process pour lui-même, sur son propre nœud
- other_node — mémoire allouée par un process pour lui-même, mais sur un nœud distant (à surveiller de près)
Un ratio numa_miss/numa_hit élevé, ou un other_node important comparé à local_node, signale un placement mémoire sous-optimal à corriger avec numactl --membind/--cpunodebind ou l'affinité NUMA propre à l'application (ex. innodb_numa_interleave sous MySQL).
Statistiques par process
numastat -p mysqld # stats mémoire NUMA du/des process correspondant au nom
numastat -p 12345 # ou directement par PID
Cette commande détaille, pour le process ciblé, combien de mémoire il a allouée sur chaque nœud NUMA. C'est la commande la plus utile en pratique pour diagnostiquer un serveur de base de données ou une JVM : si le process est épinglé (ou tourne majoritairement) sur le nœud 0 mais que sa mémoire est répartie de façon significative sur le nœud 1, c'est le signe d'un accès mémoire distant systématique et d'un gain de performance possible en corrigeant le placement (via numactl au lancement, ou la configuration NUMA propre à l'application).
Statistiques mémoire par nœud
numastat -m # vue façon "free" ou "meminfo", mais par nœud NUMA
Affiche pour chaque nœud NUMA le détail façon /proc/meminfo : mémoire totale, libre, utilisée par le cache de fichiers, par les tables de pages, par les hugepages, etc. Utile pour voir si un nœud est proche de la saturation pendant qu'un autre reste largement libre — signe qu'il faudrait répartir la charge (process, cache applicatif) plus équitablement entre les nœuds.
Lien avec numactl --hardware
numastat montre l'usage mémoire, mais pas la topologie physique du serveur. Pour voir combien de nœuds NUMA existent, quels CPU appartiennent à quel nœud et les distances entre nœuds, utiliser :
numactl --hardware # nombre de nœuds, CPU par nœud, mémoire par nœud, matrice de distances
La matrice de distances (typiquement 10 pour un accès local, 20-21 pour un accès au nœud voisin sur les architectures courantes) donne une idée chiffrée de la pénalité d'un accès mémoire distant. Croiser cette topologie avec la sortie de numastat -p permet de confirmer qu'un process mal placé subit bien une pénalité NUMA réelle, et pas seulement théorique.
Tuning bases de données et JVM
Sur les serveurs multi-socket hébergeant une base de données ou une JVM avec un gros tas mémoire, un mauvais placement NUMA est une cause fréquente et sous-diagnostiquée de lenteurs :
- MySQL/MariaDB — le buffer pool InnoDB peut être réparti (interleave) sur tous les nœuds via
innodb_numa_interleave=1, ce qui évite qu'un unique nœud NUMA sature pendant que les autres restent inutilisés. - PostgreSQL — recommandation courante de lancer le serveur avec
numactl --interleave=allpour répartir les shared buffers sur tous les nœuds, plutôt que de les laisser s'accumuler sur un seul. - JVM (Java) — l'option
-XX:+UseNUMA(avec le garbage collector Parallel ou G1 selon version) rend la JVM consciente de la topologie NUMA et tente d'allouer le tas près du thread qui l'utilise, plutôt que de le laisser figé sur un seul nœud dès le démarrage.
Dans tous les cas, la démarche est la même : numactl --hardware pour connaître la topologie, numastat -p avant/après un changement de configuration pour vérifier que le placement mémoire s'est amélioré, et une mesure de performance applicative pour confirmer le gain réel.
Voir aussi
- Vmstat — statistiques mémoire et CPU globales, sans distinction NUMA
- Processeur — informations CPU, dont la topologie multi-socket
- Mémoire — commandes générales de diagnostic mémoire