Portage de MariaDB vers IBM AIX (Partie 2) : comment AIX se met au niveau de Linux

Comment j’ai comblé un écart de performance de 23× (Spoiler : il n’y avait en réalité aucun écart)

Partie 2 : De “AIX est lent” à “AIX fait jeu égal avec Linux”.

Dans la première partie, je me suis battu avec CMake, j’ai implémenté un pool de threads à partir de zéro et j’ai livré un serveur MariaDB 11.8.5 stable pour AIX. Le serveur a passé 1 000 connexions simultanées, 11 millions de requêtes et aucune fuite de mémoire.

Ensuite, j’ai effectué une recherche vectorielle de référence.

AIX: 42 requêtes par seconde.
Linux (même matériel) : 971 requêtes par seconde.

Vingt-trois fois plus lent. Sur un matériel IBM Power S924 identique. Même version de MariaDB. Même jeu de données.

Voici l’histoire de la façon dont nous avons découvert qu’il n’y avait aucun écart de performance – juste des erreurs de configuration et un compilateur sous-optimal.

Chapitre 1 : Le sentiment d’affaissement

Il y a un genre particulier de désespoir qui vient quand on voit un écart de performance de 23x sur un matériel identique. C’est le genre de désespoir “j’aurais peut-être dû devenir fleuriste”.

Permettez-moi de planter le décor : les deux machines sont des LPARs fonctionnant sur des serveurs IBM Power S924 avec des processeurs POWER9 à 2750 MHz. Même MariaDB 11.8.5. Même ensemble de données de test – 100 000 vecteurs à 768 dimensions, utilisant l’index MHNSW (Hierarchical Navigable Small World) de MariaDB pour la recherche vectorielle.

Le critère de référence était simple : trouver les 10 voisins les plus proches d’un vecteur de requête. C’est le genre d’opération qui alimente toutes les fonctions de recherche améliorées par l’IA que tu as déjà utilisées.

Linux l’a fait en environ 1 milliseconde. AIX a mis 24 millisecondes.

Mon premier réflexe a été le déni. “Le point de référence doit être erroné”. Ce n’était pas le cas. “Peut-être que l’indice est corrompu”. Ce n’était pas le cas. “Peut-être que le réseau est lent.” Il s’agissait d’une connexion locale.

Il est temps de creuser.

Chapitre 2 : Les premiers 65x – L’importance de la configuration

Le cache qui a tout oublié

Le premier indice est venu du profileur de MariaDB. Chaque requête prenait le même temps, qu’il s’agisse de la première ou de la centième. Ce n’est pas ainsi que fonctionnent les caches.

J’ai vérifié la configuration MHNSW de MariaDB :

SHOW VARIABLES LIKE 'mhnsw%';
mhnsw_max_cache_size: 16777216

16 MO. Notre graphique vectoriel a besoin d’environ 300 Mo pour contenir la structure HNSW en mémoire.

C’est là que le bât blesse : lorsque le cache se remplit, MariaDB n’expulse pas les anciennes entrées (pas de LRU). Il jette tout et repart à zéro. Chaque. Chaque. Demande.

Imagine une bibliothèque où, lorsque les étagères sont pleines, le bibliothécaire brûle tous les livres et commande de nouveaux exemplaires. Pour chaque utilisateur.

Correction: mhnsw_max_cache_size = 4GB dans la configuration du serveur.

Résultat : 42 QPS → 112 QPS. Une amélioration de 2,7x à partir d’une seule ligne de configuration.

Le problème de la taille des pages

AIX utilise par défaut des pages de mémoire de 4 Ko. Linux sur POWER utilise des pages de 64 Ko.

Pour le modèle d’accès du MHNSW – la chasse aux pointeurs sur un graphique de 300 Mo – cela a une importance énorme. Avec des pages de 4 Ko, tu as besoin de 16x plus d’entrées TLB (Translation Lookaside Buffer) pour mapper la même quantité de mémoire. Les erreurs du TLB coûtent cher.

C’est comme si tu naviguais dans une ville. Avec des pages de 4 Ko, tu as besoin d’indications pour chaque bâtiment. Avec des pages de 64 Ko, tu obtiens des indications par quartier. C’est beaucoup plus rapide quand tu es constamment en train de sauter d’un bâtiment à l’autre.

Correction: script d’enrobage qui définit LDR_CNTRL=DATAPSIZE=64K@TEXTPSIZE=64K@STACKPSIZE=64K@SHMPSIZE=64K

Résultat : 112 QPS → 208 QPS en séquentiel, et 2 721 QPS avec 12 travailleurs en parallèle.

Le tableau d’affichage après la phase 1

ConfigurationQPS séquentielAvec 12 travailleurs
Base de référence42~42
+ 4GB cache112
+ 64K pages2082,721

Amélioration de 65x à partir de deux changements de configuration. Aucune modification du code.

Mais nous étions toujours 6x plus lents que Linux par cœur. L’enquête s’est poursuivie.

Chapitre 3 : Le mystère du décrochage entre le CPU et la mémoire

Une fois la configuration établie, j’ai sorti les outils de profilage. MariaDB possède un profileur intégré qui décompose le temps de requête par phase.

AIX:

Sending data: 4.70ms total
  - CPU_user: 1.41ms
  - CPU_system: ~0ms
  - Stalls: 3.29ms (70% of total!)

Linux:

Sending data: 0.81ms total
  - CPU_user: 0.80ms
  - Stalls: ~0.01ms (1% of total)

Le temps d’exécution de l’unité centrale était 1,8 fois plus lent sur AIX – ce qui peut s’expliquer par les différences de compilateur. Mais les blocages de la mémoire étaient 329 fois pires.

La cause première : Invalidation du cache de l’hyperviseur

Voici quelque chose que j’ai mis deux jours à comprendre : dans une LPAR (Logical Partition) partagée, l’hyperviseur POWER préempte périodiquement les processeurs virtuels pour donner du temps à d’autres partitions. Ce faisant, il peut invalider des lignes de cache L2/L3.

La traversée du graphe du MHNSW est une chasse aux pointeurs à travers 300 Mo de mémoire – littéralement le pire scénario pour l’invalidation de la mémoire cache. Tu sautes de nœud en nœud, chacun dans une partie différente de la mémoire, et l’hyperviseur vide périodiquement ton cache.

C’est comme essayer de lire un livre alors que quelqu’un ne cesse de le fermer et de le remettre sur l’étagère.

Le système Linux avait des processeurs dédiés. Le système AIX fonctionnait avec des processeurs partagés. Ce ne sont pas des pommes pour des pommes.

Mais avant de pouvoir tester les processeurs dédiés, je devais résoudre le problème du compilateur.

Chapitre 4 : L’odyssée du compilateur

Tout ce que j’ai essayé avec GCC (et pourquoi ça a échoué)

TentativeRésultatPourquoi
-flto (Optimisation du temps de connexion)ImpossibleGCC LTO nécessite le format ELF ; AIX utilise XCOFF
-fprofile-generate (PGO)Échec de la constructionErreurs de l’assembleur concernant la relocalisation relative au TOC
-ffast-mathTout se casse la figureIEEE float violations corrupt bloom filter hashing
-funroll-loopsPlus lentCache d’instruction gonflé – POWER9 n’aime pas ça
-finline-functionsPlus lentMême problème de cache I

La boîte à outils AIX GCC est construite sans support LTO. Ce n’est pas un drapeau que tu as oublié – c’est architecturalement impossible parce que l’implémentation LTO de GCC nécessite ELF, et AIX utilise XCOFF.

Les paquets MariaDB d’Ubuntu utilisent -flto=auto. Cette optimisation n’existe tout simplement pas pour AIX avec GCC.

IBM Open XL : Le rebondissement de l’intrigue

À ce stade, j’ai passé trois jours à essayer de rendre GCC plus rapide. Il est temps d’essayer quelque chose de différent.

IBM Open XL C/C++ 17.1.3 est le compilateur moderne d’IBM, basé sur LLVM/Clang. Il génère un code nettement meilleur pour POWER9 que GCC.

Pour construire MariaDB avec Open XL, il a fallu résoudre cinq problèmes différents :

  1. En-tête HTM manquant: Open XL n’a pas le fichier htmxlintrin.h de GCC. J’ai créé un stub.
  2. AR 32 bits par défaut: Les outils AIX sont par défaut en 32 bits. Définis OBJECT_MODE=64.
  3. Incompatibilité LLVM AR: Open XL’s AR ne pouvait pas gérer XCOFF. Utilise le système /usr/bin/ar.
  4. Conflits OpenSSL: Utilise -DWITH_SSL=system pour éviter les problèmes liés à WolfSSL.
  5. Chemins d’accès aux bibliothèques manquants: Explicit -L/opt/freeware/lib pour l’éditeur de liens.

Ensuite, j’ai exécuté le test de référence :

Compilateur30 requêtesPar requête
GCC 13.3.00.190s6.3ms
Open XL 17.1.30.063s2.1ms

Trois fois plus rapide. Même code source. Mêmes drapeaux d’optimisation (-O3 -mcpu=power9).

Et voici le bonus : la variance du benchmark de GCC était de 10 à 40 % entre les exécutions. La variance d’Open XL était inférieure à 2 %. Il n’y a pratiquement pas de gigue.

Pourquoi une telle différence ?

Open XL (qui est basé sur LLVM) l’a fait :

  • Meilleure planification des instructions pour l’exécution hors ordre de POWER9
  • Attribution de registres supérieurs
  • Des passes d’optimisation plus agressives

Le backend POWER/XCOFF de GCC n’est tout simplement pas aussi mature. La boîte à outils AIX GCC est fonctionnelle, mais elle n’est pas optimisée pour les charges de travail critiques en termes de performances.

Chapitre 5 : Les impasses du LTO et du PGO

L’espoir est éternel. Peut-être que les LTO et PGO d’Open XL fonctionneraient ?

LTO : L’ironie

Open XL prend en charge -flto=full sur XCOFF. Il se construit vraiment ! Mais…

Résultat : 27 % plus lent que l’Open XL non LTO.

Pourquoi ? Les bibliothèques partagées AIX nécessitent une liste d’exportation explicite (exports.exp). Avec LTO, le script de CMake a vu ~27 000 symboles à exporter.

Le principal avantage de l’OLT est d’internaliser les fonctions, c’est-à-dire de les marquer comme étant locales afin qu’elles puissent être optimisées ou mises en ligne. Lorsque tu es obligé d’exporter 27 000 symboles, aucun d’entre eux ne peut être internalisé. Les frais généraux de l’OLT (fichiers intermédiaires plus volumineux, liaison plus lente) demeurent, mais l’avantage disparaît.

C’est comme si tu payais un abonnement à une salle de sport et qu’on te disait ensuite que tu ne peux utiliser aucun des équipements.

PGO : Les profils qui n’ont jamais existé

L’optimisation guidée par le profil semblait prometteuse :

  1. Construis avec -fprofile-generate
  2. Charge de travail pour l’entraînement à la course à pied
  3. Reconstruis avec -fprofile-use
  4. Profite d’un code plus rapide

L’étape 1 a fonctionné. Étape 2… les profils ne sont jamais apparus.

J’ai lié manuellement le runtime de profilage LLVM à la bibliothèque partagée. Toujours pas de profils.

La cause première : Le runtime de profilage de LLVM utilise atexit() ou __attribute__((destructor)) pour écrire des profils à la sortie. Sur AIX avec XCOFF, la sémantique des destructeurs de bibliothèques partagées est différente de celle d’ELF. Le gestionnaire n’est tout simplement pas appelé de manière fiable pour les configurations complexes à plusieurs bibliothèques comme MariaDB.

Les cas de test simples fonctionnent. Les applications réelles ne fonctionnent pas.

Chapitre 6 : La révélation LPAR

J’avais maintenant un compilateur rapide. Il est temps de tester les processeurs dédiés et d’éliminer le problème d’invalidation du cache de l’hyperviseur.

La matrice de test

Config LPARGCCOpen XL
12 vCPUs partagés0.190s0.063s
12 plafonds dédiés0.205s0.082s
21 dédiés plafonnés0.320s0.067s

Attends. Les services partagés sont plus rapides que les services dédiés ?

Le facteur WoF

POWER9 dispose d’une fonction appelée Workload Optimized Frequency (WoF). En mode partagé avec une faible utilisation, un seul cœur peut atteindre ~3,8 GHz. Les processeurs dédiés plafonnés sont bloqués à 2750 MHz.

Pour une requête à un seul fil, le mode partagé obtient 38 % de vitesse d’horloge en plus. Cela bat la pénalité d’invalidation du cache pour cette charge de travail.

Imagine que tu choisisses entre une voiture de sport sur une autoroute avec une circulation occasionnelle (partagée) et un camion avec une voie réservée mais une limite de vitesse (dédiée plafonnée).

Le désastre du mode donateur de PowerVM

Il existe une troisième option : les processeurs dédiés en mode “Donating”, qui redonnent les cycles inactifs au pool partagé.

ModeGCCOpen XL
Plafonné0.205s0.082s
Faire un don0.325s0.085s

60% de régression avec GCC.

Chaque fois qu’une requête explose, il y a un temps de latence pour récupérer les cycles donnés. Pour les charges de travail en rafale et à un seul fil, comme les requêtes de base de données, c’est dévastateur.

Recommandation: N’utilise jamais le mode Don pour les charges de travail des bases de données.

Le 21-Core Sweet Spot

Avec 21 cœurs dédiés (contre 24 pour Linux), Open XL a atteint 0,067s – égalant presque les 0,063s du mode partagé. Le cache L3 supplémentaire apporté par plus de cœurs compense l’absence d’augmentation de la fréquence du WoF.

Chapitre 7 : Le tableau d’affichage final (rebondissement)

Nouveaux benchmarks sur du matériel POWER9 identique, janvier 2026 :

PlateformeCœurs30 requêtes
Linux24 dédié0.057s
AIX + Open XL12 partagés0.063s
AIX + Open XL21 dédié0.067s
AIX + GCC12 partagé0.190s
AIX + GCC21 dédié0.320s

Attends. Le système AIX a 21 cœurs contre 24 pour Linux. C’est 12,5 % de cœurs en moins, ce qui signifie 12,5 % de cache L3 en moins.

L’écart mesuré ? 10-18%.

Ce n’est pas un écart de performance. C’est une différence de matériel.

Avec IBM Open XL, AIX offre des performances par cœur identiques à celles de Linux. L’écart de 23x que nous avons constaté au début ? Il n’a jamais été question de la lenteur d’AIX. C’était le cas :

  1. Un cache mal configuré (16 Mo au lieu de 4 Go)
  2. Taille des pages incorrecte (4KB au lieu de 64KB)
  3. Le mauvais compilateur (GCC au lieu d’Open XL)

Le mythe “AIX est lent” est mort.

Le musée complet de l’échec

La science ne se limite pas à ce qui fonctionne – il s’agit aussi de documenter ce qui ne fonctionne pas. Voici notre mur de “bien essayé, mais non” :

Ce que nous avons essayéRésultatNotes
mhnsw_max_cache_size = 4GB5 fois plus rapideÉlimine les tressautements de la mémoire cache
LDR_CNTRL 64K pages~40% plus rapideRéduit les erreurs de la TLB
MAP_ANON_64K patch mmap~8% plus rapideAmélioration mineure du TLB
IBM Open XL 17.1.33x plus rapideMeilleur codegen POWER9
LPAR partagé (vs dédié)~25% plus rapideAugmentation de la fréquence du WoF
Open XL + LTO27% plus lentConflit d’exportation AIX
Open XL + PGONe fonctionne pasProfils non écrits
GCC LTOImpossibleXCOFF n’est pas pris en charge
GCC PGOÉchecs de constructionErreurs de relocalisation du TOC
-ffast-mathCasse MHNSWCorruption par flottaison
-funroll-loopsPireI-cache bloat
POWER VSX bloom filter41% plus lentPas de multiplication vec 64 bits sur P9
Préfixe logicielAucun effetL’hyperviseur évince les données préfixées
Réglage du DSCRBloquéL’hyperviseur contrôle le DSCR dans les LPAR partagés
Mode de don60% de régressionNe jamais utiliser pour les bases de données

Le résultat de VSX est particulièrement intéressant : nous avons implémenté un filtre Bloom SIMD en utilisant les extensions vectorielles de POWER. Il était 41 % plus lent que le scalaire. POWER9 n’a pas de multiplication vectorielle 64 bits – il faut vec_extract → multiplication scalaire → vec_insert pour chaque voie, ce qui est plus lent que de laisser le moteur Out-of-Order gérer une boucle scalaire.

Ce que j’ai appris

1. Les défauts de paiement sont plus importants que tu ne le penses

Un cache de 16 Mo par défaut a transformé des requêtes de moins d’une milliseconde en requêtes de 24 ms. C’est une pénalité de 24x pour un seul paramètre mal configuré.

Lorsque tu portes un logiciel, remets en question tous les paramètres par défaut. Ce qui fonctionne sous Linux peut ne pas fonctionner sur ta plateforme.

2. Le mythe de la lenteur d’AIX a toujours été un problème de chaîne d’outils

Avec GCC, nous étions 3 à 4 fois plus lents que Linux. Avec Open XL, nous sommes au même niveau que Linux par cœur.

La plateforme n’a jamais été lente. La chaîne d’outils par défaut n’était tout simplement pas optimisée pour les charges de travail critiques en termes de performances. Choisis le bon compilateur.

3. La virtualisation comporte des compromis cachés

Les LPAR partagés peuvent être plus rapides que les LPAR dédiés pour les charges de travail monothématiques (augmentation de la fréquence du WoF). Le mode dédié est plus efficace pour les charges de travail multithreads soutenues. Le mode don est un piège.

Connais ta charge de travail. Choisis ta configuration LPAR en conséquence.

4. Tous les ports d’optimisation n’ont pas la même valeur

LTO, PGO et la vectorisation SIMD ont tous échoué sur AIX pour diverses raisons. Les techniques qui rendent Linux rapide ne se traduisent pas toujours.

Parfois, l’optimisation “évidente” est le mauvais choix. Mesure tout.

5. Parfois, il n’y a pas d’écart du tout

Nous avons passé des jours à enquêter sur un “écart de performance” qui s’est avéré être :

  • Erreurs de configuration
  • Mauvais compilateur
  • Moins de cœurs sur le système de test

La leçon à retenir : vérifie tes données de base. Assure-toi de comparer des pommes avec des pommes avant de supposer qu’il y a un problème à résoudre.

Recommandations

Pour les utilisateurs d’AIX MariaDB

  1. Utilise la version Open XL (version 3, bientôt disponible)
  2. Règle mhnsw_max_cache_size sur au moins 4 Go pour la recherche vectorielle
  3. Conserver le LPAR partagé pour une latence de requête unique
  4. N’utilise jamais le mode don pour les bases de données
  5. Utilise des pages de 64K via le wrapper LDR_CNTRL

Pour MariaDB en amont

  1. Augmente la valeur par défaut de mhnsw_max_cache_size – 16MB est beaucoup trop petit
  2. Mettre en œuvre l’éviction LRU – jeter tout le cache en cas de débordement est brutal.
  3. N’ajoute pas le filtre bloom POWER VSX – le scalaire est plus rapide sur POWER9

Prochaines étapes

Les RPM sont publiés sur aix.librepower.org. La version 2 inclut les corrections de configuration. La version 3 avec les versions Open XL sera disponible dès que nous aurons obtenu une licence commerciale (l’évaluation expire dans 59 jours).

Priorités immédiates:

  • Licence commerciale Open XL : L’évaluation expire bientôt. Nécessité d’une licence IBM pour la version 3 du RPM de production.
  • Implémentation native de l’AIO: AIX a POSIX AIO et IOCP compatible avec Windows. Il est temps d’écrire le backend InnoDB.
  • Retour d’information sur le MHNSW en amont: La valeur par défaut de mhnsw_max_cache_size (16 Mo) est trop faible pour les charges de travail réelles ; nous suggérerons une valeur par défaut plus élevée.

Pour les organisations qui exécutent déjà des charges de travail critiques sur AIX – et il y en a beaucoup, des banques aux compagnies aériennes en passant par les systèmes de santé – la possibilité d’exécuter également MariaDB moderne et performant ouvre de nouvelles possibilités.

AIX correspond à Linux. Le mythe est mort. Et MariaDB sur AIX est prêt pour la production.

TL;DR

  • Au départ, l’écart de performance était de 23x (42 QPS contre 971 QPS).
  • Configuration du cache corrigée : Amélioration de 5x
  • Taille de page fixe : ~40% de plus
  • Passage à IBM Open XL: amélioration de 3x par rapport à GCC
  • LPAR partagé utilisé : ~25% plus rapide que le dédié (WoF boost)
  • Résultat final : NO GAP – 10% de différence = 12,5% de cœurs en moins (21 vs 24)
  • AIX atteint les mêmes performances par cœur que Linux grâce à Open XL
  • Open XL LTO : n’aide pas (27% plus lent)
  • Open XL PGO : ne fonctionne pas (problème AIX XCOFF)
  • POWER VSX SIMD : 41% plus lent que le scalaire (pas de multiplication vec 64 bits)
  • Mode donateur : 60% de régression – ne jamais utiliser pour les bases de données
  • “AIX est lent pour les bases de données open source” a toujours été un mythe de la chaîne d’outils.

Des questions ? Des idées ? Tu utilises MariaDB sur AIX et tu veux partager ton expérience ?

Ce travail fait partie de LibrePower – Unlocking IBM Power Systems through open source. RAS inégalé. Coût total de possession supérieur. Empreinte minimale 🌍

Dépôt du projet LibrePower AIX : gitlab.com/librepower/aix

SIXE