Portear MariaDB a IBM AIX | Cómo AIX empata con Linux – Parte 2

De “AIX es lento” a “AIX iguala a Linux” (si usas las herramientas adecuadas)

En la Parte 1, peleé con CMake, implementé un Thread Pool desde cero y logré una versión estable de MariaDB 11.8.5 para AIX. El servidor aguantó 1.000 conexiones concurrentes, 11 millones de consultas y cero fugas de memoria.

Entonces, lancé un benchmark de búsqueda vectorial.

  • AIX: 42 consultas por segundo (QPS).
  • Linux (mismo hardware): 971 consultas por segundo.

Veintitrés veces más lento. En idéntico hardware IBM Power S924. Misma versión de MariaDB. Mismo dataset.

Esta es la historia de cómo descubrimos que no existía tal brecha de rendimiento: solo errores de configuración y un compilador que no estaba a la altura.

Engineering debugging process visualization

Capítulo 1: Esa sensación de hundimiento

Existe un tipo particular de desesperación que sientes al ver una diferencia de rendimiento de 23x en hardware idéntico. Es ese momento en el que piensas: “quizá debería haberme hecho florista”.

Pongámonos en situación: ambas máquinas son LPARs corriendo en servidores IBM Power S924 con procesadores POWER9 a 2750 MHz. El mismo MariaDB 11.8.5. El mismo dataset de prueba: 100.000 vectores con 768 dimensiones, usando el índice MHNSW (Hierarchical Navigable Small World) de MariaDB.

La prueba era simple: encontrar los 10 vecinos más cercanos (KNN) a un vector de consulta. Es el tipo de operación que alimenta todas las funciones de búsqueda por IA (RAG) modernas.

  • Linux lo hizo en ~1 milisegundo.
  • AIX tardó 24 milisegundos.

Mi primer instinto fue la negación. “El benchmark está mal”. No lo estaba. “El índice está corrupto”. No lo estaba. “La red va lenta”. Era una conexión socket local.

Tocaba remangarse y cavar hondo.

Capítulo 2: Los primeros 65x – La configuración importa

La caché amnésica

La primera pista nos la dio el profiler de MariaDB. Cada consulta tardaba exactamente lo mismo, fuera la primera o la número cien. Las cachés no funcionan así.

Revisé la configuración MHNSW de MariaDB:

SHOW VARIABLES LIKE 'mhnsw%';
mhnsw_max_cache_size: 16777216

16 MB. Nuestro grafo vectorial necesita unos 300 MB para mantener la estructura HNSW en memoria.

Aquí está el problema: cuando la caché se llena, MariaDB no expulsa las entradas antiguas (no hay LRU). Lo tira todo y empieza de cero. En. Cada. Consulta.

Imagina una biblioteca donde, cuando las estanterías se llenan, el bibliotecario quema todos los libros y pide copias nuevas. Para cada usuario.

El arreglo: mhnsw_max_cache_size = 4GB en la configuración.

Resultado: 42 QPS → 112 QPS. Una mejora de 2.7x con una línea de configuración.

El problema del tamaño de página (Page Size)

AIX usa por defecto páginas de memoria de 4 KB. Linux en POWER usa páginas de 64 KB.

Para el patrón de acceso de MHNSW —que consiste en perseguir punteros a través de un grafo de 300 MB— esto es crítico. Con páginas de 4 KB, necesitas 16 veces más entradas en el TLB (Translation Lookaside Buffer) para mapear la misma memoria. Los fallos de TLB (TLB misses) son caros.

Piénsalo como navegar por una ciudad. Con páginas de 4 KB, necesitas instrucciones paso a paso para cada edificio. Con páginas de 64 KB, te dan instrucciones por barrios. Mucho más rápido cuando te mueves constantemente.

El arreglo: Un script wrapper que establece LDR_CNTRL=DATAPSIZE=64K@TEXTPSIZE=64K@STACKPSIZE=64K@SHMPSIZE=64K.

Resultado: 112 QPS → 208 QPS secuenciales, y 2.721 QPS con 12 workers paralelos.

Marcador tras la Fase 1

ConfiguraciónQPS SecuencialCon 12 workers
Base42~42
+ 4 GB caché112
+ 64K pages2082.721

Mejora de 65x con dos cambios de configuración. Sin tocar código.

Pero seguíamos siendo 6 veces más lentos que Linux por núcleo. La investigación continuó.

Capítulo 3: El misterio de CPU vs. Memory Stalls

Con la configuración arreglada, saqué las herramientas de profiling. MariaDB tiene un profiler interno que desglosa el tiempo por fases.

AIX:

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

Linux:

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

El tiempo de CPU era 1.8x más lento en AIX (esperable por diferencias de compilador). Pero los “stalls” (paradas de memoria) eran 329 veces peores.

La causa raíz: Invalidación de caché por el Hipervisor

Tardé dos días en descubrir esto: en una LPAR compartida, el hipervisor POWER interrumpe periódicamente a los procesadores virtuales para dar tiempo a otras particiones. Cuando lo hace, puede invalidar líneas de caché L2/L3.

Recorrer un grafo MHNSW es una “persecución de punteros” a través de 300 MB de memoria: literalmente el peor escenario para la invalidación de caché. Saltas de nodo en nodo y el hipervisor te vacía la caché periódicamente.

Es como intentar leer un libro mientras alguien te lo cierra y lo devuelve a la estantería cada dos por tres.

El sistema Linux tenía procesadores dedicados. El AIX estaba en modo compartido. No estábamos comparando manzanas con manzanas.

Pero antes de probar procesadores dedicados, tenía que arreglar el problema del compilador.

Capítulo 4: La odisea del compilador

Todo lo que intenté con GCC (y por qué falló)

IntentoResultadoRazón
-flto (Link Time Optimization)ImposibleGCC LTO requiere formato ELF; AIX usa XCOFF.
-fprofile-generate (PGO)Falla compilaciónErrores del ensamblador con reubicación TOC.
-ffast-mathRompe todoViolaciones IEEE corrompen el hash del Bloom filter.
-funroll-loopsMás lentoInfla la caché de instrucciones (I-cache bloat). A POWER9 no le gusta.

El toolchain de GCC en AIX no tiene soporte LTO real. No es un flag que olvidé: es arquitecturalmente imposible porque la implementación LTO de GCC requiere ELF, y AIX usa XCOFF. Los paquetes de MariaDB en Ubuntu usan -flto=auto. Esa optimización simplemente no existe para AIX con GCC.

IBM Open XL: El giro de guion

Llevaba tres días intentando que GCC fuera más rápido. Era hora de probar algo diferente.

IBM Open XL C/C++ 17.1.3 es el compilador moderno de IBM, basado en LLVM/Clang. Genera un código significativamente mejor para POWER9 que GCC.

Compilar MariaDB con Open XL requirió resolver cinco problemas:

  1. Falta header HTM: Open XL no tiene el htmxlintrin.h de GCC. Creé un stub.
  2. 32-bit por defecto: Las herramientas de AIX son de 32 bits. Tuve que forzar OBJECT_MODE=64.
  3. LLVM AR incompatible: El AR de Open XL no manejaba bien XCOFF. Usé el /usr/bin/ar del sistema.
  4. Conflictos OpenSSL: Usar -DWITH_SSL=system para evitar líos con wolfSSL.
  5. Rutas de librerías: Flags explícitos -L/opt/freeware/lib para el linker.

Y entonces, lancé el benchmark:

Compilador30 ConsultasPor consulta
GCC 13.3.00.190s6,3 ms
Open XL 17.1.30.063s2,1 ms

Tres veces más rápido. Mismo código fuente. Mismos flags de optimización (-O3 -mcpu=power9).

Y un detalle clave: la varianza con GCC era del 10-40% entre ejecuciones. Con Open XL fue menor al 2%. Una estabilidad roca.

¿Por qué tanta diferencia?

Open XL (al estar basado en LLVM) tiene:

  • Mejor planificación de instrucciones (instruction scheduling) para la ejecución fuera de orden (Out-of-Order) de POWER9.
  • Asignación de registros superior.
  • Pasadas de optimización más agresivas.

Capítulo 5: Los callejones sin salida de LTO y PGO

La esperanza es lo último que se pierde. ¿Quizás LTO y PGO sí funcionan en Open XL?

LTO: La ironía

Open XL soporta -flto=full en XCOFF. ¡Compila! Pero…

Resultado: 27% más lento que Open XL sin LTO.

¿Por qué? Las librerías compartidas en AIX requieren una lista explícita de exportaciones (exports.exp). El script de CMake vio ~27.000 símbolos para exportar.

La ventaja principal de LTO es la internalización de funciones (hacerlas locales para optimizarlas o hacer inlining). Cuando te obligan a exportar 27.000 símbolos, no puedes internalizar nada. Te quedas con el overhead de LTO pero sin sus ventajas.

Es como pagar el gimnasio y que te digan que no puedes usar ninguna máquina.

PGO: Los perfiles que nunca existieron

Profile Guided Optimization sonaba prometedor:

  1. Compilar con -fprofile-generate
  2. Ejecutar carga de entrenamiento
  3. Recompilar con -fprofile-use

El paso 1 funcionó. El paso 2… los perfiles nunca aparecieron.

La causa raíz: El runtime de profiling de LLVM usa destructores al salir. En AIX con XCOFF, la semántica de los destructores en librerías compartidas es distinta a ELF. Simplemente, no se llaman de forma fiable en configuraciones complejas como MariaDB.

Capítulo 6: La revelación de la LPAR

Ahora tenía un compilador rápido. Toca probar procesadores dedicados y eliminar el problema de la caché del hipervisor.

La matriz de pruebas

Configuración LPARGCCOpen XL
12 vCPUs compartidas0.190s0.063s
12 dedicadas (Capped)0.205s0.082s
21 dedicadas (Capped)0.320s0.067s

Espera. ¿El modo Compartido es más rápido que el Dedicado?

El factor WoF

POWER9 tiene una función llamada Workload Optimized Frequency (WoF). En modo compartido con baja utilización, un solo núcleo puede acelerar hasta ~3.8 GHz (turbo). Los procesadores dedicados “Capped” suelen estar limitados a la frecuencia base (2750 MHz).

Para una consulta mono-hilo, el modo compartido gana un 38% extra de velocidad de reloj. Eso supera la penalización de la caché para esta carga específica.

Es como elegir entre un Ferrari en una autopista con tráfico ocasional (Compartido) vs un camión en un carril exclusivo pero con limitador de velocidad (Dedicado).

El desastre del modo Donación

Hay una tercera opción: procesadores dedicados en modo “Donación” (Donating), que ceden ciclos ociosos al pool compartido.

ModoGCCOpen XL
Capped0.205s0.082s
Donating0.325s0.085s

Regresión del 60% con GCC.
Cada vez que llega una consulta (burst), hay una latencia para recuperar los ciclos donados. Para bases de datos, esto es devastador.

Recomendación: Nunca uses modo Donating para bases de datos.

Capítulo 7: El marcador final (el verdadero giro)

Nuevos benchmarks en hardware POWER9 idéntico, Enero 2026:

PlataformaNúcleos30 Consultas
Linux24 dedicados0.057s
AIX + Open XL12 compartidos0.063s
AIX + Open XL21 dedicados0.067s

Un momento. El sistema AIX tiene 21 núcleos vs los 24 de Linux. Eso es un 12.5% menos de núcleos (y menos caché L3).

¿La “diferencia” medida? Entre 10-18%.

Eso no es una diferencia de rendimiento de software. Es una diferencia de hardware pura y dura.

Con IBM Open XL, AIX ofrece un rendimiento por núcleo idéntico a Linux. ¿La diferencia de 23x con la que empezamos? Nunca fue culpa de AIX. Fue culpa de:

  1. Una caché mal configurada (16MB vs 4GB).
  2. Tamaño de página incorrecto (4 KB vs 64 KB).
  3. El compilador equivocado (GCC vs Open XL).

El mito de “AIX es lento” ha muerto.

El Museo de los Intentos Fallidos

La ciencia no va solo de lo que funciona, sino de documentar lo que no funciona. Aquí mi muro de “buen intento”:

Qué probamosResultadoNotas
mhnsw_max_cache_size = 4GB5x más rápidoElimina el “thrashing” de caché.
LDR_CNTRL 64K pages~40% más rápidoReduce fallos de TLB.
IBM Open XL 17.1.33x más rápidoMejor generación de código POWER9.
Open XL + LTO27% más lentoConflicto con exportaciones AIX.
POWER VSX Bloom Filter41% más lentoNo hay multiplicación de vectores de 64-bit en P9.
Software PrefetchingSin efectoEl hipervisor desaloja los datos antes de usarlos.
DSCR TuningBloqueadoEl hipervisor controla el DSCR en LPAR compartida.

El dato del VSX es interesante: implementamos un Bloom Filter SIMD usando extensiones vectoriales de POWER. Fue un 41% más lento que el escalar. POWER9 no tiene multiplicación vectorial de 64 bits, por lo que simularla es más lento que dejar que el motor Out-of-Order maneje el bucle escalar.

Lecciones aprendidas

1. Los “defaults” los carga el diablo

Una caché por defecto de 16MB convertía consultas de 1ms en 24ms. Una penalización de 24x por un parámetro de configuración. Cuestiona siempre los valores por defecto al portar software.

2. El mito de la lentitud era un problema de Toolchain

Con GCC, éramos 3-4x más lentos que Linux. Con Open XL, igualamos a Linux. La plataforma nunca fue lenta; la cadena de herramientas por defecto (GCC en AIX) no está optimizada para alto rendimiento.

3. No todas las optimizaciones se portan

LTO, PGO y vectorización SIMD fallaron en AIX por razones arquitecturales. Lo que hace rápido a Linux no siempre se traduce directamente. Mídelo todo.

Recomendaciones para usuarios

Si usas MariaDB en AIX:

  1. Usa la build con Open XL (versión 3, próximamente).
  2. Configura mhnsw_max_cache_size a mínimo 4GB si usas vectores.
  3. Usa LPAR compartida para latencia de consultas individuales (WoF ayuda).
  4. Nunca uses modo “Donating” para BBDD.
  5. Fuerza páginas de 64K con el wrapper LDR_CNTRL.

¿Qué sigue?

Los RPMs están publicados en aix.librepower.org. La Release 2 incluye los arreglos de configuración. La Release 3 (con Open XL) está en camino.

Para las organizaciones que ya corren cargas críticas en AIX —bancos, aseguradoras, sanidad— la opción de correr también MariaDB moderno con rendimiento nativo abre un mundo de posibilidades.

AIX iguala a Linux. El mito ha muerto. Y MariaDB en AIX está listo para producción.


TL;DR

  • Empezamos con un gap de 23x de rendimiento (42 QPS vs 971 QPS).
  • Arreglo de caché: Mejora de 5x.
  • Arreglo de Page Size (64K): ~40% extra.
  • Cambio a compilador IBM Open XL: 3x mejor que GCC.
  • Resultado final: GAP CERO (la diferencia del 10% corresponde a tener 12.5% menos núcleos).
  • “AIX es lento para Open Source” siempre fue un mito causado por usar el compilador incorrecto.

SIXE