Evolución de Zen: cambios entre generaciones que realmente notas

¿Te fue útil?

No “sientes” una nueva generación de CPU porque una captura de benchmark se ve más bonita. La sientes cuando la latencia p99 deja de tener picos a las 10:03 todos los días, cuando tus nodos de almacenamiento dejan de quedarse atrás en el scrub, cuando la factura eléctrica deja de subir más rápido que tu plantilla y cuando tu canal de incidentes vuelve a ser aburrido.

Las actualizaciones de Zen —Zen 1 hasta Zen 4, y la variante Zen 4c— están llenas de cambios que no aparecen en las diapositivas de marketing y que son dolorosamente evidentes en producción. Esta es la guía práctica: qué cambia realmente entre generaciones, cómo se manifiesta en sistemas reales y cómo demostrarlo con comandos en lugar de impresiones.

Lo que realmente notas: las diferencias visibles en producción

La mayoría de los equipos compran CPUs como compran paraguas: según lo mojados que estuvieron la última vez. Es comprensible, pero lleva a expectativas equivocadas. Entre generaciones de Zen, los cambios que percibes se agrupan en cinco áreas:

1) La latencia en cola (tail latency) se comporta distinto

Zen no es solo “más IPC”. Cambian la disposición de la caché, los complejos de núcleos, las velocidades del fabric y los controladores de memoria. Esas cosas modifican la forma de las distribuciones de latencia. La sensación más notable de Zen 3 para muchos servicios sensibles a la latencia fue que la comunicación entre núcleos dejó de ser tan extraña porque el límite CCX cambió (más adelante hay más detalles). Zen 4 suele sentirse como “igual, pero más rápido”, hasta que notas que la memoria y el PCIe pueden convertirse en el nuevo techo.

2) Los techos de ancho de banda se mueven (y también los cuellos de botella)

En plataformas antiguas puedes estar limitado por CPU. En las nuevas, puedes volverte limitado por memoria o por E/S sin tocar el código. Cuando llega PCIe 5, las canalizaciones de almacenamiento pueden pasar de “PCIe es el límite” a “el límite es el firmware NVMe, la configuración del IOMMU o la afinidad de IRQ”. Las actualizaciones son cómo descubres qué parte de tu stack es la más lenta.

3) La densidad de núcleos lo cambia todo operativamente

Más núcleos no solo significan mayor rendimiento. Significan más sensibilidad NUMA, más contención por cachés compartidas, más decisiones sobre enrutamiento de interrupciones y más formas de dañarte con una afinación de kernel naíf de “talla única”. La diferencia entre “CPU rápida” y “sistema rápido” es si tus decisiones conscientes de topología siguen el ritmo.

4) Energía y térmicas dejan de ser ruido de fondo

El rendimiento por vatio es donde Zen ha sido despiadadamente eficiente en el datacenter. Pero un comportamiento turbo más agresivo y sockets más densos hacen que la “refrigeración” pase a ser una entrada de ingeniería, no una ocurrencia tardía de las instalaciones. Si alguna vez viste un nodo reducir su frecuencia bajo una prueba sostenida y luego comportarse bien en producción, ya conoces este problema.

5) La madurez del firmware y del microcódigo importa más de lo que quieres

Las plataformas nuevas se lanzan con una “personalidad de vida temprana”. Mejora con el tiempo. Tu trabajo es tratar BIOS, AGESA y microcódigo como dependencias de producción. Si eso suena molesto, sí. También: es más barato que el tiempo de inactividad.

Una cita para mantener la honestidad, de Gene Kranz: «Fracasar no es una opción.» Esa línea se repite con frecuencia; trátala como una idea parafraseada sobre rigor bajo presión, no como un eslogan de rendimiento.

Broma #1: Actualizar CPUs para arreglar un problema de arquitectura es como comprar una impresora más rápida para mejorar tu caligrafía.

Hechos y contexto que explican las partes extrañas

Tomarás mejores decisiones si recuerdas algunos hechos concretos sobre cómo llegamos hasta aquí:

  1. Zen (2017) fue el “reinicio” de AMD tras la era Bulldozer, recuperando núcleos de alto IPC y volviendo a competir seriamente en servidores.
  2. EPYC “Naples” (Zen 1) usó un enfoque MCM multi-dado; la topología era potente pero fácil de configurar mal para cargas sensibles a NUMA.
  3. Zen 2 (2019) pasó a chiplets: chiplets de CPU en 7 nm más un dado I/O. Esa separación es la base de gran parte de lo que experimentas después (especialmente en comportamiento de memoria/E/S).
  4. Zen 3 (2020) reordenó núcleos y caché en un CCD unificado de 8 núcleos, reduciendo ciertas penalizaciones entre núcleos y haciendo más barato que “un hilo hable con otro hilo”.
  5. Zen 4 (2022) introdujo DDR5 y PCIe 5 en plataformas EPYC mainstream, moviendo la frontera del cuello de botella hacia afuera y exponiendo tuberías de E/S descuidadas.
  6. Las variantes con 3D V-Cache cambiaron la conversación de afinación: puedes comprar caché en lugar de esperar que la latencia de memoria mejore. Es un trade-off que deberías cuantificar.
  7. Mitigaciones de seguridad (época Spectre y posteriores) cambiaron valores por defecto del kernel y el comportamiento del hipervisor; comparaciones entre generaciones sin contexto de mitigaciones suelen ser ficción.
  8. Linux aprendió la topología con el tiempo. Mejoras en el planificador y en el equilibrio NUMA hacen que “mismo hardware, distinto kernel” pueda parecer un cambio de generación.
  9. Infinity Fabric y su relación con las frecuencias de memoria han sido un tema recurrente; influyen en la latencia entre dados y por eso la configuración de memoria no es una casilla de verificación cualquiera.

Zen por generación: los cambios que importan en operaciones

Seré algo injusto con los nombres de marketing y me centraré en lo que te despierta a las 2 a. m. La “sensación” de cada generación es una combinación de diseño de núcleo, caché, memoria, E/S y madurez de plataforma.

Zen 1 / Zen+ (era Naples): “Es rápido, pero la topología te castigará si finges que es Intel”

Los servidores Zen 1 fueron un shock para el mercado: muchos núcleos, muchas lanes, buen rendimiento por dólar. También introdujeron a muchos equipos en la realidad de que NUMA no es teoría. Naples podía comportarse como varias máquinas unidas si no cuidabas la población de memoria y la colocación de procesos.

Lo que notas: latencia en cola impredecible bajo charla entre sockets o entre dados, y cargas que escalan hasta cierto punto—y luego se desploman.

Qué hacer: aprende tus nodos NUMA, fija servicios críticos y deja de fingir que “repartir en todos los núcleos” es siempre bueno.

Zen 2 (Rome): “Chiplets, mejor escalado y menos sorpresas—salvo si saturas la memoria”

Zen 2 hizo que la arquitectura de chiplets fuera mainstream en servidores. El dado I/O centralizó controladores de memoria y E/S. Esto a menudo hizo la plataforma más fácil de razonar, pero también convirtió el ancho de banda de memoria en un recurso compartido que puedes quemar más rápido con conteos de núcleos altos.

Lo que notas: mejor rendimiento por núcleo y escalado más suave; pero cargas intensivas en memoria empiezan a mostrar que “el ancho de banda es el nuevo CPU”.

Qué hacer: trata los canales de memoria como capacidad de primera clase. “Más DIMMs” puede ser una decisión de rendimiento, no solo de capacidad.

Zen 3 (Milan): “CCX unificado: la latencia deja de ser ‘misteriosa’ para muchas cargas”

La gran victoria operativa de Zen 3 fue que dentro de un CCD, los núcleos comparten una L3 unificada en lugar de particiones CCX más pequeñas. Esto reduce ciertas penalizaciones para hilos que comparten datos pero caen en núcleos diferentes.

Lo que notas: mejoras en p99 para servicios con mucho estado compartido de solo lectura (caches, tablas de enrutamiento, ciertas cargas JVM), más la menor sensación de “¿por qué mover el proceso a otro núcleo cambia la latencia?”

Qué hacer: revisa reglas antiguas de pinning. Algunos de los hacks necesarios en Zen 1/2 se vuelven innecesarios—o perjudiciales.

Zen 4 (Genoa): “DDR5 y PCIe 5 mueven los postes; energía, firmware y afinación de E/S se oyen más”

La historia real de Zen 4 es la plataforma: DDR5, PCIe 5 y mayores conteos de núcleos. Si manejas almacenamiento, redes o cualquier cosa que sea básicamente “mover bytes sin atascarse”, lo sentirás.

Lo que notas: margen de throughput y la capacidad de consolidar más cargas por socket—hasta que la gestión de interrupciones, la configuración del IOMMU o la sensibilidad a la latencia de memoria te alcancen.

Qué hacer: reserva tiempo para afinación de BIOS/firmware y alineación IRQ/NUMA. También: espera peculiaridades iniciales de plataforma. Planifica ventanas de parches.

Zen 4c (variantes de núcleos densos): “Más núcleos, comportamiento por núcleo ligeramente distinto; las elecciones de scheduling importan”

Las variantes de núcleos densos existen para maximizar el rendimiento por unidad de rack y por vatio. La “sensación” es que puedes meter más trabajo, pero debes ser más deliberado sobre qué servicios van allí (orientados a throughput, menos sensibles a latencia) frente a los de mayor frecuencia.

Lo que notas: gran throughput para trabajos paralelos, pero algunos componentes de hilo único o sensibles a latencia pueden necesitar aislamiento o SKU distintos.

Qué hacer: separa una “capa de latencia” y una “capa de throughput” en la planificación de capacidad. No las mezcles por conveniencia.

Topología, NUMA, CCD/CCX: donde se esconde el rendimiento

Si quieres un modelo mental que explique la mayoría de las “rarezas de Zen”, es este: tu CPU no es un monolito. Es un vecindario de islas de cómputo conectadas por carreteras. Algunas carreteras son rápidas. Otras se atascan. Tu trabajo es mantener a los vecinos que hablan mucho lo más cerca posible.

Qué cambió entre generaciones de Zen

  • Zen 1/2: dominios de caché más pequeños significaban más fallos de caché entre dominios para conjuntos de trabajo compartidos, que aparecían como picos de latencia cuando cambiaba la colocación de hilos.
  • Zen 3: L3 unificada por CCD redujo la penalización de “dos hilos comparten datos pero no una porción de caché”. Esto es un cambio práctico y medible.
  • Zen 4: las mejoras de plataforma elevan los techos, pero la complejidad topológica crece. Aumentan los conteos de núcleos, cambian los canales de memoria y puedes tener más nodos NUMA según el BIOS y el SKU.

Por qué deben importarle a los SRE

Las decisiones de topología aparecen como:

  • Deriva en latencia p95/p99 cuando el kernel migra hilos entre núcleos/nodos NUMA.
  • Utilización de CPU desigual (un nodo NUMA caliente, otros inactivos) porque la localidad de memoria impulsa el rendimiento efectivo.
  • Jitter en almacenamiento cuando las IRQs caen en núcleos ocupados del nodo NUMA “equivocado” respecto al dispositivo PCIe.

Regla: si una carga tiene estado compartido y te importa la latencia, o la mantienes en un dominio de caché o aceptas el coste y lo mides. La esperanza no es un plan.

Memoria y E/S: ancho de banda, latencia, PCIe y realidad del almacenamiento

En producción, las CPUs rara vez fallan por ser “demasiado lentas”. Fallan por esperar. Esperar a la memoria. Esperar a bloqueos. Esperar a las completaciones de E/S. Cada generación de Zen cambia esos patrones de espera.

Ancho de banda de memoria: el habilitador silencioso (y el limitador silencioso)

A medida que suben los conteos de núcleos, el ancho de banda por núcleo puede caer si los canales de memoria no escalan proporcionalmente o si subutilizas DIMMs. DDR5 en Zen 4 ayuda, pero también tienta a la gente a usar menos DIMMs “porque cabe la capacidad”. Luego te llaman cuando las tormentas de compactación y las pausas de GC empeoran.

Latencia de memoria: el impuesto que pagas en los fallos

La latencia se modela por la velocidad de memoria, timings, comportamiento del controlador y la distancia del núcleo a la memoria adjunta al nodo NUMA relevante. Los cambios de caché en Zen 3 reducen la frecuencia con que pagas ese impuesto para ciertos patrones. Zen 4 aún puede castigarte por mala localidad—solo que más rápido.

PCIe: cuando “más lanes” no es lo mismo que “más rendimiento”

PCIe 4 a PCIe 5 duplica el ancho de banda teórico, y en el mundo real no obtendrás 2× a menos que el resto de tu stack pueda seguir el ritmo: firmware NVMe, capa de bloques del kernel, traducción IOMMU, enrutamiento de IRQ y disponibilidad de CPU para completaciones. Los ingenieros de almacenamiento aprenden esto pronto: el bus rara vez es el único bus.

Cambios en la “sensación” específica de almacenamiento

  • Mayor potencial de IOPS significa que puedes alcanzar los techos de sobrecarga de CPU en el manejo de interrupciones NVMe antes.
  • Mayor potencial de reconstrucción/scrub es real, pero solo si la colocación de hilos de checksum/compresión y el ancho de banda de memoria no te están combatiendo.
  • Convergencia red + almacenamiento (NICs rápidas + SSDs rápidos) te empuja a territorio de “alineación de IRQ y NUMA” quieras o no.

Broma #2: PCIe 5 es genial—ahora puedes mover datos el doble de rápido hacia el lugar donde tu aplicación espera por un mutex.

Virtualización y planificadores: la sección “¿por qué se ralentizó esta VM?”

La evolución de la plataforma Zen cambia la historia de la virtualización en dos sentidos: topología y mitigaciones. Hipervisores y kernels son mejores que antes, pero siguen haciendo tonterías cuando no les dices qué significa “cerca”.

Ubicación de VM y vNUMA: acercar la mentira a la verdad

Si una VM cree que tiene acceso uniforme a la memoria mientras el host tiene una topología multi-nodo NUMA, estás básicamente pidiendo al invitado que tome malas decisiones de scheduling a alta velocidad. El pinning y vNUMA no son “micro-optimización”. Son cómo evitas que el tráfico entre nodos se coma tu rendimiento.

Mitigaciones y microcódigo: las comparaciones de rendimiento necesitan contexto

Las mitigaciones del kernel pueden cambiar entre versiones del SO, y las actualizaciones de microcódigo pueden cambiar el comportamiento. Cuando alguien dice, “Zen 4 solo es 10% más rápido que Zen 3 para nuestra carga”, tu primera pregunta debería ser: “¿Qué cambió en el kernel y el firmware, y estamos midiendo lo mismo?”

Tareas prácticas: comandos, salidas, decisiones (12+)

Esta es la parte que puedes copiar en tus runbooks. Cada tarea incluye: un comando, qué significa la salida y una decisión que tomar a partir de ello. Son orientadas a Linux porque allí viven la mayoría de servidores Zen.

Tarea 1: Identificar la generación de CPU y stepping

cr0x@server:~$ lscpu | egrep 'Model name|CPU\(s\)|Socket|Thread|NUMA node\(s\)'
Model name:                           AMD EPYC 7B13 64-Core Processor
CPU(s):                               128
Socket(s):                            2
Thread(s) per core:                   2
NUMA node(s):                         8

Significado: Ves la línea del modelo (ayuda a mapear a la generación Zen) y el conteo de nodos NUMA (una gran pista sobre la topología).

Decisión: Si los nodos NUMA son muchos, planifica trabajo de colocación/pinning antes de culpar a la aplicación.

Tarea 2: Confirmar la topología NUMA y el mapeo CPU→nodo

cr0x@server:~$ numactl --hardware
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 64412 MB
node 0 free: 51230 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 64500 MB
node 1 free: 52110 MB
...

Significado: Qué núcleos pertenecen a cada nodo NUMA y memoria disponible por nodo.

Decisión: Para servicios sensibles a la latencia, fija CPU y memoria a un nodo que tenga acceso local al NIC/NVMe.

Tarea 3: Comprobar velocidad de memoria y canales poblados (señal rápida)

cr0x@server:~$ sudo dmidecode -t memory | egrep 'Locator:|Speed:|Configured Memory Speed:|Size:'
Locator: P0_DIMM_A1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s
Locator: P0_DIMM_B1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s

Significado: Si realmente estás funcionando a las velocidades esperadas y si hay DIMMs presentes.

Decisión: Si la velocidad configurada es menor de la esperada, arregla la configuración del BIOS o la población de DIMMs antes de afinar el software.

Tarea 4: Ver si estás limitado por CPU o atrapado en espera de E/S

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

12:10:01 AM  CPU   %usr  %nice  %sys  %iowait  %irq  %soft  %steal  %idle
12:10:02 AM  all  62.11   0.00  8.40    0.25   0.10   1.20    0.00  27.94
12:10:02 AM    0  95.00   0.00  3.00    0.00   0.00   0.00    0.00   2.00
...

Significado: Alto %usr implica trabajo de CPU; alto %iowait implica que la CPU espera por E/S.

Decisión: Si iowait es alto, deja de “afinar CPU” e inspecciona almacenamiento/red. Si un CPU está al máximo, sospecha de afinidad de IRQ o de un hilo caliente único.

Tarea 5: Detectar presión en la cola de ejecución (saturación del planificador)

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
12  0      0 5210432  91232 1832448    0    0    12   144 9800 21000 71  9 20  0  0
18  0      0 5209120  91232 1832600    0    0     0   512 9950 24000 76 10 14  0  0

Significado: r son tareas ejecutables. Cuando está consistentemente por encima de los núcleos disponibles (o por encima del grupo de núcleos que te importa), estás sobresuscrito.

Decisión: Si la cola de ejecución es alta y la latencia es mala, reduce la consolidación o fija workloads críticos lejos de vecinos ruidosos.

Tarea 6: Comprobar comportamiento de frecuencia y throttling

cr0x@server:~$ lscpu | egrep 'CPU max MHz|CPU MHz'
CPU MHz:                               2890.123
CPU max MHz:                           3650.0000

Significado: Frecuencia actual vs máxima.

Decisión: Si CPU MHz está muy por debajo de lo esperado bajo carga, revisa límites de potencia y throttling térmico en BIOS/BMC; no pierdas tiempo “optimizando código” primero.

Tarea 7: Verificar la política del cpufreq governor

cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
performance

Significado: El governor afecta la rampa de frecuencia y el comportamiento en estado estacionario.

Decisión: Para servicios de baja latencia, prefiere performance (o perfiles tuned) a menos que las restricciones de potencia sean explícitas y medidas.

Tarea 8: Inspeccionar el comportamiento de balance NUMA del kernel

cr0x@server:~$ cat /proc/sys/kernel/numa_balancing
1

Significado: El balance NUMA automático puede migrar páginas/memorias por localidad, a veces causando jitter de latencia.

Decisión: Si ves picos de latencia periódicos que se alinean con migraciones, considera deshabilitarlo para workloads fijos, pero prueba—no lo hagas en modo copia ciega.

Tarea 9: Comprobar la localidad real de memoria de un proceso

cr0x@server:~$ pidof myservice
24819
cr0x@server:~$ numastat -p 24819
Per-node process memory usage (in MBs) for PID 24819 (myservice)
Node 0   Node 1   Node 2   Node 3   Node 4   Node 5   Node 6   Node 7   Total
-----    -----    -----    -----    -----    -----    -----    -----    -----
Anon     812.3     19.5      3.1      0.2      0.1      0.0      0.0      0.0   835.2
File      42.0      1.0      0.0      0.0      0.0      0.0      0.0      0.0    43.0

Significado: La mayor parte de la memoria está en el Nodo 0, con pequeñas asignaciones remotas en otros.

Decisión: Si la memoria está dispersa entre nodos, fija con numactl o con CPUAffinity/NUMAPolicy de systemd para latencia predecible.

Tarea 10: Inspeccionar la localidad del dispositivo PCIe (qué nodo NUMA posee el dispositivo)

cr0x@server:~$ lspci -nn | egrep 'Non-Volatile|Ethernet'
41:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
c1:00.0 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6] [15b3:101b]
cr0x@server:~$ cat /sys/bus/pci/devices/0000:41:00.0/numa_node
2
cr0x@server:~$ cat /sys/bus/pci/devices/0000:c1:00.0/numa_node
6

Significado: El NVMe está más cerca del nodo NUMA 2; la NIC del nodo 6.

Decisión: Coloca hilos de almacenamiento cerca del nodo 2, hilos de red cerca del nodo 6, o acepta la penalización cross-fabric y mídela.

Tarea 11: Comprobar la distribución de IRQ (problema común en Zen: “por qué se está fundiendo un núcleo”)

cr0x@server:~$ grep -E 'nvme|mlx|eth' /proc/interrupts | head
  180:  9812234          0          0          0   PCI-MSI 524288-edge      nvme0q0
  181:        0          0          0          0   PCI-MSI 524289-edge      nvme0q1
  190:  5021132          0          0          0   PCI-MSI 532480-edge      mlx5_comp0

Significado: Que todas las interrupciones estén cayendo en CPU0 (primera columna) es señal de alarma a menos que lo hayas fijado deliberadamente así.

Decisión: Si las interrupciones están concentradas, habilita y afina irqbalance o fija las IRQs a CPUs locales al nodo NUMA del dispositivo.

Tarea 12: Confirmar comportamiento de colas NVMe y latencia

cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

Device            r/s     w/s   rMB/s   wMB/s  rrqm/s  wrqm/s %rrqm %wrqm r_await w_await aqu-sz  %util
nvme0n1        2200.0  1800.0   350.0   280.0     0.0     0.0  0.00  0.00   0.40    0.55   2.10  78.00

Significado: await es latencia; aqu-sz indica profundidad de cola; %util indica saturación.

Decisión: Si %util está cerca de 100 y await crece, el almacenamiento está saturado. Si await es bajo pero la app va lenta, sospecha de CPU/bloqueos/red.

Tarea 13: Ver si estás limitado por ancho de banda de memoria (rápido y sucio)

cr0x@server:~$ perf stat -a -e cycles,instructions,cache-misses,LLC-load-misses,task-clock -- sleep 5
 Performance counter stats for 'system wide':

   98,234,112,991      cycles
   73,120,443,210      instructions              #    0.74  insn per cycle
    1,223,110,992      cache-misses
      401,223,114      LLC-load-misses
       5,002.12 msec   task-clock

       5.000891981 seconds time elapsed

Significado: IPC bajo más muchos fallos de LLC suele apuntar a stalls por memoria (no siempre, pero es una pista fuerte).

Decisión: Si los stalls de memoria dominan, prioriza la localidad de caché, reduce accesos remotos y comprueba población/velocidades de DIMM antes de perseguir flags del compilador.

Tarea 14: Comprobar migraciones de CPU (indicio de jitter de latencia)

cr0x@server:~$ perf stat -p 24819 -e context-switches,cpu-migrations -a -- sleep 10
 Performance counter stats for 'system wide':

       210,554      context-switches
        12,321      cpu-migrations

      10.004112343 seconds time elapsed

Significado: Muchas migraciones de CPU pueden significar que tus hilos rebotan entre núcleos/nodos NUMA.

Decisión: Si el p99 es malo y las migraciones son altas, considera afinidad de CPU, cgroup cpusets o tunning del planificador. No te limites a “añadir réplicas”.

Tarea 15: Validar estado de hugepages (importante para VM y BD)

cr0x@server:~$ grep -E 'HugePages|Hugepagesize' /proc/meminfo
HugePages_Total:     8192
HugePages_Free:      7901
Hugepagesize:        2048 kB

Significado: Hugepages configuradas y disponibles.

Decisión: Si dependes de hugepages y están agotadas, tendrás picos de latencia y presión en la TLB; ajusta la asignación o corrige fugas/fragmentación.

Tarea 16: Comprobar flags de KVM y virtualización anidada (hosts cloud/VM)

cr0x@server:~$ lsmod | grep kvm
kvm_amd               155648  0
kvm                  1064960  1 kvm_amd
cr0x@server:~$ cat /sys/module/kvm_amd/parameters/nested
0

Significado: Si la virtualización anidada está habilitada en el host.

Decisión: Habilita solo si la necesitas. La anidada puede complicar rendimiento y depuración; el “por si acaso” es cómo acumulas sobrecarga misteriosa.

Guion de diagnóstico rápido: encuentra el cuello de botella rápidamente

Esta es la secuencia de triaje que uso cuando alguien dice: “Actualizamos de Zen X a Zen Y y no es más rápido” o “es más rápido pero la latencia empeoró”. No improvises. Ejecuta el guion.

Primero: confirma la realidad de la plataforma (5 minutos)

  1. CPU + conteo NUMA (lscpu): ¿estás en el hardware que crees? ¿Cambió la exposición NUMA por ajustes del BIOS?
  2. Velocidad y población de memoria (dmidecode): ¿estás funcionando a los MT/s esperados? ¿Están los canales subpoblados?
  3. Governor y frecuencia (scaling_governor, lscpu): ¿estás atrapado en una política de ahorro de energía?

Segundo: clasifica el cuello de botella (10 minutos)

  1. CPU vs iowait (mpstat): alto usuario/sistema vs alto iowait.
  2. Presión de cola de ejecución (vmstat): ¿estás sobresuscrito?
  3. Pista de stalls de memoria (perf stat): IPC bajo + muchos LLC misses sugiere comportamiento limitado por memoria.

Tercero: alineación de topología (15–30 minutos)

  1. Localidad de memoria del proceso (numastat -p): ¿está el proceso mayoritariamente local?
  2. Nodo NUMA del dispositivo (/sys/bus/pci/.../numa_node): ¿están NVMe/NIC cerca de los núcleos que hacen el trabajo?
  3. Distribución de interrupciones (/proc/interrupts): ¿las IRQs están “fundiendo” un núcleo?

Condición de parada: una vez que encuentres una clase de cuello de botella (CPU, memoria, E/S, topología), deja de coleccionar métricas aleatorias. Haz un cambio, mide y solo entonces prosigue.

Tres mini-historias corporativas (anónimas, plausibles y algo dolorosas)

Mini-historia 1: El incidente causado por una suposición errónea

La empresa migró una flota de servidores API de Zen 2 a Zen 4. Las pruebas de rendimiento fueron geniales: throughput arriba, latencia media abajo. Lo desplegaron gradualmente. En una semana llegó el incidente: picos de latencia p99 cada pocos minutos, solo en la flota nueva, solo bajo tráfico mixto.

El equipo on-call hizo lo que todos hacen bajo presión: miraron el uso de CPU. Estaba bien. Miraron el GC. Bien. Miraron el balanceador de carga. También estaba bien, probablemente por despecho.

La suposición errónea fue sutil: “NUMA lo maneja el kernel ahora”. En los hosts antiguos, la NIC y los hilos más ocupados del servicio ocurrieron por casualidad en el mismo nodo NUMA por el cableado del chasis. En los hosts nuevos, la NIC quedó en otro nodo. El servicio además estaba configurado con un conjunto de CPU que fijaba sus workers a los “primeros” núcleos —conveniente, estable y ahora muy lejos de la NIC.

Cada paquete hacía un viaje extra por el fabric. Bajo tráfico ligero no importaba. Bajo carga, la latencia extra y los fallos de caché cross-node se convirtieron en un precipicio periódico, porque el nodo ocupado se saturó más y el kernel empezó a migrar cosas para compensar.

La solución fue aburrida: alinear la afinidad de CPU de los workers con el nodo NUMA de la NIC, y asegurar que la política de memoria coincidiera. Los picos desaparecieron inmediatamente. Nadie quiso admitir que era “solo” topología, pero los gráficos no entienden de orgullo.

Mini-historia 2: La optimización que salió mal

Un equipo de almacenamiento actualizó servidores de metadatos de Zen 3 a Zen 4. Viendo margen, un ingeniero aumentó la concurrencia: más hilos worker, colas más profundas, tamaños de batch mayores. La idea era “usar todos esos núcleos”. Y funcionó—hasta que dejó de hacerlo.

El primer síntoma no fue rendimiento; fue variabilidad. La latencia se volvió más irregular, no más lenta en promedio. Los trabajos de mantenimiento nocturnos empezaron a solaparse con picos diurnos de forma que antes no ocurría. Nada estaba “al máximo” en las métricas obvias.

El contraefecto fue clásico: la nueva concurrencia empujó la carga de CPU-bound a bound por ancho de banda de memoria. Zen 4 movió el techo, pero el patrón de acceso de la carga—mucho pointer chasing, muchos fallos de caché—significaba que la CPU pasaba tiempo esperando. Los hilos extra aumentaron la contención y la churn de caché, y el sistema gastó más tiempo coordinando que haciendo trabajo útil.

Revirtieron el cambio de concurrencia y re-probaron. El throughput bajó un poco, pero el p99 se estabilizó y el solapamiento de mantenimiento dejó de causar impacto visible. Luego hicieron la solución real: shardear deliberadamente el metadata caliente y fijar los hilos más parlanchines en un dominio de localidad más estrecho.

La lección: mayores conteos de núcleos no significan que debas aumentar la concurrencia a ciegas. Es fácil crear un cuello de botella más rápido y llamarlo mejora.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

Un equipo de plataforma tenía una costumbre que otros equipos ridiculizaban: cada nueva generación de hardware pasaba por la misma lista de aceptación. Versión de BIOS, nivel de microcódigo, versión de kernel, política de governor, ajustes de IOMMU y un pequeño conjunto de “smoke benchmarks” reproducibles. No era glamoroso. No recibía aplausos.

Durante un despliegue de Zen 4, notaron una pequeña pero consistente anomalía: un lote de nodos tenía menor frecuencia sostenida bajo carga y peor p99 en sus pruebas smoke. No era catastrófico. Solo “raro”. La diferencia se correlacionó con un perfil BIOS ligeramente distinto que venía en ese lote del proveedor.

Detuvieron el despliegue solo para esos nodos, corrigieron el perfil BIOS y reanudaron. Dos semanas después, otro equipo descubrió que sus propios nodos estaban haciendo throttling en picos de jobs por lotes—porque no estandarizaron el firmware y asumieron que los valores por defecto eran adecuados.

El equipo de plataforma no pareció heroico en el momento. Tampoco tuvieron un outage. Su práctica era aburrida, y lo aburrido era la idea.

Errores comunes: síntomas → causa raíz → solución

Esta es la sección que pegas en un ticket de incidente. Síntomas específicos, causas probables y soluciones que realmente cambian el resultado.

1) Síntoma: p99 peor después de la actualización, latencia promedio mejor

Causa raíz: desajuste de topología (hilos lejos del NIC/NVMe), aumento de migraciones de CPU o efectos secundarios del balance NUMA en sistemas con más núcleos.

Solución: Comprueba el nodo NUMA del dispositivo y fija los hilos del servicio en consecuencia; verifica la localidad de memoria con numastat; reduce migraciones con afinidad/cpuset; considera deshabilitar el balance NUMA para servicios fijados.

2) Síntoma: benchmarks NVMe mejoraron, pero la E/S de la aplicación no

Causa raíz: la app está limitada por CPU en manejo de syscalls/interrupciones/completions; IRQs concentradas en un núcleo; overhead de IOMMU/remapeo de interrupciones; colas mal configuradas.

Solución: Inspecciona /proc/interrupts; distribuye IRQs; asegúrate de que las colas estén configuradas; mide uso de CPU en softirq; fija hilos de E/S cerca del dispositivo.

3) Síntoma: Un núcleo al 100% en sys mientras otros están ociosos

Causa raíz: afinidad de IRQ fijada a una sola CPU (o irqbalance deshabilitado), o un hilo kernel caliente.

Solución: Reactiva irqbalance o configura manualmente la afinidad de IRQ; verifica con /proc/interrupts y vuelve a comprobar bajo carga.

4) Síntoma: El throughput escala hasta N hilos y luego se estanca

Causa raíz: saturación de ancho de banda de memoria, contenido de locks o tráfico cross-NUMA dominando.

Solución: Usa perf stat para buscar stalls; reduce accesos cross-node; divide locks; considera estructuras de datos amigables a caché; no añadas hilos a ciegas.

5) Síntoma: “Nuevas CPUs son más lentas” en un host de VMs

Causa raíz: oversubscription de vCPU, vNUMA mal configurado, mitigaciones activadas de distinto modo o cambio en la política de energía del host.

Solución: Comprueba cola de ejecución y tiempo de steal; alinea vNUMA con la topología física; asegura políticas consistentes de kernel/microcódigo; fija el governor.

6) Síntoma: Reconstrucción/scrub de almacenamiento más lenta en nodos nuevos

Causa raíz: hilos de checksum/compresión programados lejos de los discos; contención de ancho de banda de memoria con servicios co-localizados; canales de memoria subpoblados.

Solución: Coloca workers de almacenamiento cerca del nodo NUMA del NVMe; reserva núcleos; popula canales de memoria correctamente; mide ancho de banda y stalls de CPU.

7) Síntoma: Picos de latencia aleatorios cada pocos minutos

Causa raíz: trabajo de kernel en background (migraciones de páginas NUMA, kswapd), oscilaciones térmicas/energéticas o tareas de mantenimiento periódicas que ahora colisionan por distintos perfiles de rendimiento.

Solución: correlaciona picos con migraciones (perf migrations, cambios en numastat), comprueba frecuencias y throttling, reprograma mantenimiento y aísla cargas.

Listas de verificación / plan paso a paso

Lista de planificación de actualización (antes de comprar o reasignar flota)

  1. Clasifica las cargas: capa de latencia vs capa de throughput. Ponlas en los SKU adecuados (las partes de núcleos densos no son mágicas para latencia de un solo hilo).
  2. Inventaria los cuellos de botella hoy: CPU, ancho de banda de memoria, latencia de memoria, E/S o contención de locks. Usa primero el guion “Diagnóstico rápido”.
  3. Decide qué significa “mejor”: p99, throughput a p99 fijo, watts por petición, tiempo de rebuild, ratio de consolidación. Elige dos, no siete.
  4. Planifica gobernanza de firmware: versión de BIOS/AGESA, política de microcódigo, versión de kernel. Trátalos como dependencias fijadas con despliegue controlado.
  5. Diseña política NUMA: ¿vas a fijar? ¿Usar cpusets? ¿Dejar que el scheduler vaya libre? Decide deliberadamente.
  6. Verifica reglas de población de memoria: canales llenos para ancho de banda, no solo capacidad.
  7. Mapea la localidad de dispositivos: ¿dónde están conectados NICs y NVMe? Asegura que el diseño del chasis coincida con tu modelo de colocación de cargas.

Lista de aceptación (primer rack de nueva generación)

  1. Ejecuta lscpu y registra modelo CPU, nodos NUMA, max MHz.
  2. Ejecuta dmidecode y confirma que la velocidad configurada de memoria coincide con lo esperado.
  3. Confirma governor: performance (o la política elegida).
  4. Comprueba distribución de IRQ bajo carga sintética; corrige si está concentrada.
  5. Ejecuta un canario a nivel de servicio y compara p50/p99, no solo throughput.
  6. Corre pruebas smoke de almacenamiento/red y asegura que la localidad del dispositivo NUMA coincide con la estrategia de colocación de hilos.

Lista operativa (continuo)

  1. Estandariza perfiles BIOS y audita la deriva.
  2. Rastrea cambios de kernel y microcódigo como parte de las líneas base de rendimiento.
  3. Alerta sobre anomalías de frecuencia (relojes sostenidos por debajo de lo esperado bajo carga).
  4. Alerta sobre hotspots de IRQ (un solo CPU recibiendo interrupciones desproporcionadas).
  5. Revisa presión de consolidación: colas de ejecución, tiempo de steal y efectos de vecinos ruidosos.

Preguntas frecuentes

1) ¿Es Zen 3 la generación “grande” para apps sensibles a latencia?

A menudo, sí—porque el cambio en dominios de caché (L3 unificada por CCD) reduce ciertas penalizaciones entre núcleos. Pero la respuesta real depende de cuánto tu carga comparta datos entre hilos y de cuán sensible sea a fallos de caché.

2) ¿Por qué mi p99 empeoró después de moverme a una CPU más nueva?

Porque cambiaste topología y comportamiento, no solo velocidad. Causas comunes: hilos ahora corren lejos del NIC/NVMe; aumentaron las migraciones de CPU; el balance NUMA empezó a mover páginas; o entraste en un nuevo cuello de botella (ancho de banda de memoria, manejo de IRQ).

3) ¿Necesito fijar procesos en sistemas Zen modernos?

Si te importa la latencia predecible, sí, al menos para componentes críticos. Si ejecutas jobs por lotes/throughput, a menudo puedes confiar en el scheduler. Mezclar ambos sin fijación es cómo obtienes “rápido en promedio, terrible cuando importa”.

4) ¿DDR5 es siempre una mejora?

No automáticamente. Eleva los techos de ancho de banda, pero la latencia y la configuración importan. Subpoblar canales puede borrar las ganancias. Mide con tu carga, no con la esperanza.

5) ¿Cómo sé si estoy limitado por memoria después de una actualización Zen?

Busca IPC bajo con muchos LLC misses (perf stat) y escalado que deja de mejorar al añadir hilos. Luego valida que la memoria es local (numastat) y que canales/velocidades están configurados correctamente.

6) ¿Cuál es el problema “oculto” más común en nodos de almacenamiento en nuevas generaciones Zen?

Localidad de interrupciones y colocación de CPU respecto a NVMe. El hardware es suficientemente rápido como para que tus errores de enrutamiento de IRQs se vuelvan el cuello de botella.

7) ¿Debería deshabilitar el balance NUMA?

Para servicios fijados y sensibles a latencia, puede reducir el jitter. Para sistemas multi-tenant de propósito general, puede mejorar la eficiencia general. La respuesta correcta es: pruébalo con tu carga exacta y compara p99, no solo la media.

8) ¿Las generaciones Zen cambian algo sobre el comportamiento de ZFS?

ZFS depende de CPU para checksums/compresión, ancho de banda de memoria para ARC y cargas pesadas en metadata, y E/S para latencia de vdev. Zen más nuevo puede acelerar las partes de CPU, pero también hace más importante la localidad de IRQ y la configuración de memoria.

9) ¿Cuál es una forma práctica de comparar generaciones Zen de manera justa?

Mantén constantes: versión de kernel, política de mitigaciones, configuración de BIOS, población/velocidades de memoria, colocación de almacenamiento/NIC y versión de la carga. Luego compara a p99 fijo o throughput fijo—no dejes que la métrica se desvíe.

Conclusión: siguientes pasos que realmente puedes hacer

La evolución de Zen es real y la notas—pero no siempre donde lo indica la hoja de especificaciones. Zen 3 mitigó muchos problemas de latencia al cambiar dominios de caché. Zen 4 movió el techo de la plataforma con DDR5 y PCIe 5, lo que significa que tus hábitos antiguos de “suficiente” en E/S y topología ahora pueden ser tu cuello de botella.

Siguientes pasos que rinden rápido:

  1. Ejecuta el guion de diagnóstico rápido en un nodo representativo por generación. No adivines.
  2. Mapea la localidad de tus dispositivos (NIC/NVMe → nodo NUMA) y alinea hilos críticos en consecuencia.
  3. Audita la configuración de memoria: canales poblados y velocidades configuradas, no solo GB totales.
  4. Comprueba la distribución de IRQ bajo carga y corrige hotspots antes de que se conviertan en “saturación de CPU misteriosa”.
  5. Estandariza firmware y líneas base de kernel para la flota y trata la deriva como un riesgo de producción.

Si haces esas cinco cosas, las actualizaciones de Zen dejarán de ser un salto de fe y se convertirán en lo que deben ser: un cambio de ingeniería que puedes razonar, medir y desplegar sin sorpresas.

← Anterior
Seguridad de zfs destroy: las comprobaciones que evitan «Ups, dataset equivocado»
Siguiente →
Debian 13 “No se puede localizar el paquete»: repositorio, arquitectura y trampas de sources.list (y soluciones)

Deja un comentario