Núcleos de marketing: cuando los números en un nombre engañan

¿Te fue útil?

Compras un servidor “de 64 núcleos”, mueves una carga sensible a la latencia y… nada se acelera. De hecho, se vuelve más extraño: algunas solicitudes vuelan, otras se detienen,
y los paneles de control se contradicen. Alguien pregunta: “¿Estamos limitados por la CPU?” y de repente la mitad de la sala hace benchmarks y la otra mitad negocia con finanzas.

Aquí la palabra “núcleo” deja de ser un sustantivo técnico y se convierte en un verbo de marketing. El número en el SKU no es una garantía de rendimiento,
latencia, o incluso de una planificación predecible. Es una pista. A veces útil. A menudo una trampa.

Qué significa realmente un “núcleo de marketing”

Un “núcleo de marketing” es lo que la página del producto quiere que creas que ejecutará tu código. Un núcleo real es el conjunto de recursos de ejecución que en verdad
completan tus instrucciones al ritmo que tu carga exige. Esos dos están relacionados, pero no son lo mismo.

En sistemas modernos, “conteo de núcleos” puede significar cualquiera de lo siguiente según quién hable:

  • Núcleos físicos (núcleos de CPU distintos con sus propias unidades de ejecución y cachés L1/L2 privadas).
  • Hilos de hardware (SMT/Hyper-Threading: dos o más hilos programables que comparten las mismas unidades de ejecución).
  • Núcleos de eficiencia vs núcleos de rendimiento (diseños heterogéneos donde “un núcleo” ni siquiera es de la misma clase).
  • vCPU (abstracción de la nube o virtualización que puede mapear a hilos de hardware, segmentos temporales, o algo intermedio).
  • “Núcleos equivalentes” (unidades definidas por el proveedor o para licencias pensadas para normalizar entre arquitecturas, a menudo fallando cómicamente).

Tu trabajo, como responsable de la disponibilidad y los presupuestos, es traducir “conteo de núcleos” a rendimiento alcanzable para tu carga:
rendimiento por segundo, latencia, comportamiento en cola y aislamiento ante fallos. Eso significa entender topología, comportamiento turbo, ancho de banda de memoria, jerarquía de cachés
y política del planificador—no solo contar cosas.

Una verdad más directa: los errores más caros ocurren cuando el conteo de núcleos es exacto, pero irrelevante. Puedes tener núcleos reales y aun así
estar limitado por la latencia de memoria, red, almacenamiento, contención de locks, pausas de GC, o licencias por núcleo.

Por qué los números en un nombre engañan (y cómo lo hacen)

1) SMT/Hyper-Threading: duplicar “CPU” sin duplicar rendimiento

SMT es una tecnología legítima: rellena huecos de ejecución y mejora el rendimiento en muchas cargas. No son “dos núcleos.”
Son dos hilos de hardware compitiendo por las mismas unidades de ejecución, cachés y, a menudo, por el mismo presupuesto de potencia/temperatura.

Si tu carga ya satura los puertos de ejecución de un núcleo (común en bucles ajustados, criptografía, compresión, algunos operadores de BD), SMT ayuda menos.
Si tu carga se queda esperando memoria o por fallos de predicción de saltos, SMT puede ayudar más. “Puede” requiere muchas condiciones.

Lo engañoso: los paneles y las descripciones de instancias en la nube pueden contar hilos de hardware como CPUs. Eso infla los números y cambia las expectativas.

2) Núcleos heterogéneos: P-cores y E-cores no son intercambiables

Un “núcleo” en una CPU híbrida puede ser un núcleo de rendimiento (grande, ancho, rápido) o un núcleo de eficiencia (más pequeño, más lento, más eficiente en energía).
El planificador decide dónde van tus hilos, y no todos los planificadores lo hacen bien bajo carga—especialmente en entornos con contenedores con límites de CPU, pinning o kernels antiguos.

Si ejecutas servicios críticos de latencia, te importa la planificación en el peor caso. Si ejecutas batch, te importa el rendimiento total por vatio.
“Conteo total de núcleos” mezcla ambos en un número fácil de imprimir y difícil de razonar.

3) Turbo, límites de potencia y frecuencia “en todos los núcleos”

A los vendedores les encanta publicitar la frecuencia turbo máxima. Ese número suele ser un mejor escenario para un número pequeño de núcleos activos bajo condiciones térmicas ideales.
Tu vida real es la “frecuencia con todos los núcleos bajo carga sostenida, en un rack, en una sala cálida, después de seis meses de polvo.”

El conteo de núcleos interactúa con la potencia. Muchas CPUs no pueden ejecutar todos los núcleos a la misma frecuencia alta simultáneamente. Añade instrucciones AVX intensivas y puedes ver
una caída adicional de frecuencia. Tu compra de “más núcleos” puede comprarte una menor velocidad por núcleo exactamente bajo la carga que buscabas.

4) NUMA: el impuesto silencioso de “más sockets, más núcleos”

Añade sockets y añades dominios NUMA. La memoria adjunta a un socket es más lenta de acceder desde el otro socket. Esa penalización aparece como mayor
latencia cola, amplificación de contención de locks y misterios del tipo “es rápido en microbenchmark pero lento en producción”.

NUMA no es un bug; es física y empaquetado. El error es asumir que tu software es consciente de NUMA cuando no lo es.

5) vCPU en la nube: un número que puede significar “hilo de hardware”, “cuota” o “time share”

En la nube, vCPU a menudo corresponde a un hilo de hardware. Pero las características de rendimiento dependen de la contención en el host, la variabilidad del modelo de CPU
y la política de planificación. Algunas familias de instancias te dan núcleos dedicados; otras te dan “casi tuyos a menos que alguien más haga ruido”.

El nombre suele implicar una línea base estable que no existe. Necesitas medir.

6) Licenciamiento: “núcleos” como unidad de facturación, no de cómputo

El licenciamiento por núcleo es donde los núcleos de marketing se convierten en núcleos legales. Algunos proveedores cuentan núcleos físicos; otros cuentan hilos; algunos aplican multiplicadores por familia CPU;
algunos tienen mínimos por socket. Tu adquisición puede elegir una CPU por “más núcleos por dólar” y luego descubrir que la factura del software se duplicó.

Si ejecutas bases de datos propietarias, motores analíticos o pilas de virtualización, el licenciamiento puede dominar el coste del hardware. “Conteo de núcleos” pasa a ser un problema de presupuesto
antes que una característica de rendimiento.

Broma #1: Un chip “de 64 núcleos” es como una bolsa “familiar” de patatas: técnicamente cierto, pero no te dice cuánto te va a saciar.

Hechos y contexto histórico que puedes usar en debates

Estos son puntos cortos y concretos que puedes soltar en reuniones de dimensionamiento para alejar decisiones del pensamiento mágico.

  1. Las antiguas “guerras de MHz” en x86 terminaron porque la frecuencia chocó con los límites de potencia y calor. La industria pivotó hacia multicore porque los relojes dejaron de escalar como antes.
  2. Hyper-Threading se difundió ampliamente en la era del Intel Pentium 4. Mejoró el rendimiento en algunas cargas, pero también expuso problemas de planificación y contención de caché.
  3. NUMA ha existido durante décadas en servidores de gama alta. Lo que cambió es que las cajas commodity obtuvieron múltiples sockets y chiplets, trayendo comportamiento tipo NUMA a flotas “normales”.
  4. Los chiplets (CPU multi-die) aumentaron los conteos de núcleos más rápido que el ancho de banda de memoria. Más núcleos por socket no significa automáticamente más memoria por núcleo o ancho de banda por núcleo.
  5. “Núcleo” se convirtió en una unidad de licenciamiento en software empresarial antes de ser una unidad de precio en la nube. Por eso algunos términos de licencias aún asumen sockets y núcleos físicos.
  6. Instrucciones AVX y vectores anchos pueden provocar reducciones de frecuencia. “Misma CPU, mismos núcleos” pueden ejecutar más lento dependiendo de la mezcla de instrucciones.
  7. Las mejoras del planificador de Linux para núcleos heterogéneos son relativamente recientes. La versión del kernel importa cuando mezclas P-cores/E-cores o diseños tipo big.LITTLE.
  8. Las familias de instancias en la nube a menudo ocultan variaciones de modelo de CPU bajo el mismo nombre. Dos instancias con el mismo conteo de vCPU pueden tener IPC y comportamiento de caché materialmente distintos.
  9. Los benchmarks tipo SPEC hicieron que los proveedores optimizaran para cargas específicas. No es hacer trampa; es la realidad. Pero significa que tu carga puede comportarse distinto que las gráficas de portada.

Modos de fallo: cómo los equipos se ven engañados en producción

“Conteos de núcleos engañosos” no es una queja teórica. Se convierte en alertas en on-call porque los equipos dimensionan sistemas por la variable equivocada.
Aquí están los patrones que aparecen repetidamente en postmortems.

La falacia de los núcleos iguales

Los equipos asumen que 32 núcleos en la CPU A equivalen a 32 núcleos en la CPU B. En realidad puedes comparar:
diferente IPC, diferentes tamaños de caché, distintos canales de memoria, distinta frecuencia con todos los núcleos y diferente topología.
“Mismos núcleos” se convierte en una regresión de rendimiento con un lazo de compra bonito.

La mala interpretación de “CPU alta”

Alta utilización de CPU no es automáticamente “limitación por CPU.” Puedes estar girando en esperas de locks, haciendo reintentos, comprimiendo logs porque el almacenamiento es lento,
o ejecutando trabajo del kernel por interrupciones desbalanceadas. La CPU es donde aparece el dolor, no siempre donde empieza.

La confusión por cuotas de contenedores

En Kubernetes, un pod puede estar estrangulado por límites de CPU aun cuando el nodo está mayormente ocioso. Los desarrolladores ven poca CPU del nodo y asumen margen.
Mientras tanto, la cuota CFS está silenciosamente asfixiando el rendimiento y alargando la latencia en la cola.

La sorpresa NUMA

Un servicio es “rápido en instancias pequeñas, lento en las grandes.” Esa es la firma de NUMA. Máquinas más grandes añaden dominios de memoria; los hilos de la app
vagan entre ellos; la localidad de caché muere; la latencia se dispara. Más núcleos, peor comportamiento.

El búmeran del licenciamiento

Alguien elige el SKU de más núcleos para “prepararse para el futuro”, y luego descubre que la licencia de la base de datos se cobra por núcleo con un mínimo por socket.
Llega la revisión financiera. De repente “preparado para el futuro” se convierte en “revertir y pedir disculpas.”

Tres microhistorias corporativas (anonimizadas, dolorosamente plausibles)

Microhistoria 1: Un incidente causado por una suposición errónea

Una compañía SaaS de tamaño medio migró su flota de API de una generación antigua de máquinas de 16 núcleos a nuevas máquinas de 32 núcleos.
Las nuevas cajas eran más baratas por núcleo y anunciaban mayor frecuencia turbo. Compras encantadas; el equipo SRE cautelosamente optimista.

En una semana, la rotación on-call empezó a ver picos intermitentes de latencia cola en la API, especialmente durante ráfagas de tráfico.
Nada obvio: la CPU promediaba 40–60%, el load average parecía “bien” y no había picos de errores—solo solicitudes lentas y clientes enfadados.

El equipo asumió que “más núcleos” significaba más concurrencia. Así que aumentaron el conteo de workers y los pools de hilos.
Eso empeoró los picos. Ahora el servicio ocasionalmente alcanzaba timeouts internos y tormentas de reintentos, lo que inflaba aún más la CPU.

La causa raíz resultó ser el cruce NUMA y la presión de ancho de banda de memoria. Las máquinas nuevas tenían más núcleos pero diferente configuración de canales de memoria,
y la carga—parseo pesado de JSON más TLS más una cache compartida en memoria—era sensible a la latencia de memoria y a la localidad de caché.
Los hilos migraban entre nodos NUMA, convirtiendo aciertos de caché en fallos remotos bajo ráfagas.

Las correcciones fueron aburridas y efectivas: fijar los pools más calientes a un nodo NUMA, alocar memoria localmente y limitar la concurrencia para casar con el ancho de banda de memoria.
La flota quedó estable—pero con un objetivo de “núcleos utilizados” menor que antes. El titular del postmortem fue directo: “Compramos núcleos; necesitábamos ancho de banda.”

Microhistoria 2: Una optimización que salió mal

Un equipo de plataforma de datos ejecutaba un servicio de ingestión distribuida que comprimía cargas antes de escribir en almacenamiento de objetos.
Pasaron de una CPU de 24 núcleos a una de 48 núcleos “más núcleos por el mismo precio”, esperando que la compresión escalara linealmente.

Hicieron lo que hacen los buenos ingenieros: optimizaron. Subieron el nivel de compresión. Aumentaron la paralelización. Ajustaron buffers.
El throughput en un benchmark de nodo único subió bien, y el cambio se desplegó.

En producción, la latencia explotó y el throughput cayó. Los nodos empezaron a acumular backpressure, y un sistema downstream comenzó a hacer timeouts.
La CPU estaba saturada, pero no de una forma “hacemos trabajo útil” limpia. Los cambios de contexto eran altos. Las colas de ejecución largas. El i/o wait creció de forma extraña.

El rendimiento por núcleo nuevo bajo carga sostenida era menor de lo esperado por límites de potencia y la mezcla de instrucciones.
Su librería de compresión usaba instrucciones vectoriales que disparaban reducciones de frecuencia. Más hilos solo forzaban a la CPU a un estado estable más lento.
Peor: la paralelización adicional produjo más escrituras más pequeñas y más operaciones de metadata, creando amplificación de I/O en la ruta de almacenamiento.

Revirtieron la optimización, luego la reintrodujeron con límites: menos hilos de compresión, escrituras coalescidas y un objetivo de frecuencia estable con todos los núcleos en vez de pico turbo.
La lección quedó: escalar una etapa limitada por CPU puede descubrir y empeorar una etapa limitada por I/O, y “más núcleos” puede ser un atajo hacia una meseta de frecuencia más lenta.

Microhistoria 3: Una práctica aburrida pero correcta que salvó el día

Una organización financiera planificó una gran actualización de base de datos. El proveedor recomendó un servidor más grande con mayor conteo de núcleos.
El equipo de plataforma no discutió; simplemente hizo su preflight estándar: captura de topología, benchmarking base y confirmación de licencias.

La captura de topología mostró dos sockets, múltiples nodos NUMA por socket y SMT activado. Las pruebas base mostraron que la carga era sensible a
la latencia single-thread para algunas consultas y sensible al ancho de banda de memoria para analítica. No era sensible al conteo bruto de hilos.

La comprobación de licencias mostró que la licencia de la BD era por núcleo físico con un mínimo por socket y un multiplicador según la familia de CPU.
El “servidor de mayor conteo de núcleos” habría aumentado el coste de licencias materialmente sin mejorar las consultas que eran el cuello de botella.

Eligieron otro SKU: menos núcleos, mayor frecuencia sostenida, mejor configuración de memoria y disposición NUMA predecible.
También configuraron pinning de CPU para los procesos más calientes y validaron el plan con una reproducción de trazas de producción.

No pasó nada dramático durante la actualización. Ningún incidente. Ninguna heroica nocturna. Fue tan anodino que la dirección casi se olvidó de que existió,
que es el mayor cumplido que puede recibir un equipo de operaciones.

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

El objetivo aquí no es coleccionar trivialidades. El objetivo es dejar de argumentar basándote en páginas de SKU y empezar a tomar decisiones basadas en la máquina frente a ti.
Cada tarea incluye: un comando, salida de ejemplo, qué significa y la decisión que tomas a partir de ello.

Task 1: Confirmar qué piensa el SO que son “CPUs”

cr0x@server:~$ nproc
128

Qué significa: El SO ve 128 CPUs programables (CPUs lógicas). Esto suele ser “núcleos físicos × hilos SMT”, pero también podría estar limitado por cpuset.

Decisión: Trata este número como una superficie de planificación, no como “128 núcleos reales.” Siguiente paso: mapear la topología.

Task 2: Inspeccionar la topología de la CPU (núcleos, hilos, sockets, NUMA)

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

Qué significa: 64 núcleos físicos, SMT=2, un socket, pero cuatro nodos NUMA (disposición por chiplets). NUMA importa incluso en un solo socket.

Decisión: Para cargas sensibles a latencia, planifica pinning NUMA y pruebas de localidad de memoria. Para cargas de throughput, haz benchmarks de escalado por nodo NUMA.

Task 3: Ver qué CPUs lógicas comparten un núcleo (hermanos SMT)

cr0x@server:~$ lscpu -e=CPU,CORE,SOCKET,NODE | head
CPU CORE SOCKET NODE
0   0    0      0
1   0    0      0
2   1    0      0
3   1    0      0
4   2    0      0
5   2    0      0
6   3    0      0
7   3    0      0
8   4    0      0

Qué significa: CPU 0 y 1 son dos hilos en el mismo núcleo físico, etc.

Decisión: Si tu carga satura núcleos o es crítica en latencia, considera fijar a un hilo por núcleo primero y luego expandir si ayuda.

Task 4: Comprobar el comportamiento de frecuencia de la CPU en reposo

cr0x@server:~$ sudo apt-get -y install linux-tools-common linux-tools-$(uname -r) >/dev/null 2>&1
cr0x@server:~$ sudo turbostat --Summary --quiet --interval 1 --num_iterations 1
CPU     Avg_MHz   Busy%   Bzy_MHz  TSC_MHz  PkgWatt
-       1420      6.15    3220     3000     68.12

Qué significa: Bajo carga ligera, los núcleos ocupados están haciendo boost (Bzy_MHz más alto que Avg_MHz). Esto te dice casi nada sobre comportamiento sostenido con todos los núcleos.

Decisión: Si dimensionas para throughput sostenido, prueba con concurrencia e instrucción mix representativos.

Task 5: Confirmar el gobernador de CPU y la política energética

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

Qué significa: “performance” mantiene la frecuencia alta. “powersave” (en algunos sistemas) puede estar bien, pero a veces perjudica la latencia.

Decisión: Para servicios de baja latencia, prefiere comportamiento de frecuencia predecible. Para flotas batch, mide la relación potencia vs throughput.

Task 6: Medir rápidamente escalado por núcleo vs todos los núcleos (prueba de sanidad)

cr0x@server:~$ sudo apt-get -y install sysbench >/dev/null 2>&1
cr0x@server:~$ sysbench cpu --cpu-max-prime=20000 --threads=1 run | egrep 'events per second|total time'
events per second:   381.12
total time:          10.0004s
cr0x@server:~$ sysbench cpu --cpu-max-prime=20000 --threads=64 run | egrep 'events per second|total time'
events per second:   20112.47
total time:          10.0031s

Qué significa: El escalado es razonable aquí, pero no confíes demasiado: esta prueba es intensiva en cómputo y puede no coincidir con tu mezcla de producción.

Decisión: Usa esto como una comprobación de “la máquina no está rota”. Para decisiones, benchmarkea tu carga real o una reproducción de trazas.

Task 7: Detectar throttling de CPU por límites térmicos/energía

cr0x@server:~$ dmesg -T | egrep -i 'throttl|thermal|powercap' | tail -n 5
[Mon Jan 22 10:14:03 2026] intel_rapl_common: Found RAPL domain package
[Mon Jan 22 10:15:41 2026] CPU0: Core temperature above threshold, cpu clock throttled
[Mon Jan 22 10:15:42 2026] CPU0: Core temperature/speed normal

Qué significa: Hubo throttling. Eso convierte el “conteo de núcleos” en una historia bonita y el “rendimiento real” en un objetivo móvil.

Decisión: Arregla la refrigeración/flujo de aire, verifica ajustes BIOS de potencia y vuelve a correr benchmarks sostenidos. No ajustes software en una plataforma térmicamente inestable.

Task 8: Comprobar disposición NUMA y memoria libre por nodo

cr0x@server:~$ numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 64000 MB
node 0 free: 51000 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 64000 MB
node 1 free: 12000 MB
node 2 cpus: 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
node 2 size: 64000 MB
node 2 free: 52000 MB
node 3 cpus: 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
node 3 size: 64000 MB
node 3 free: 50000 MB

Qué significa: El nodo 1 tiene poca memoria libre comparado con los otros. Si tu proceso cae allí, puede asignar memoria de forma remota y pagar en latencia.

Decisión: Rebalancea el uso de memoria, fija procesos lejos de nodos constriñidos, o arregla la estrategia de asignador/pinning.

Task 9: Verificar si tu proceso sufre asignaciones NUMA remotas

cr0x@server:~$ pidof nginx
2142
cr0x@server:~$ sudo numastat -p 2142 | head -n 8
Per-node process memory usage (in MBs) for PID 2142 (nginx)
        Node 0  Node 1  Node 2  Node 3   Total
Huge       0.0     0.0     0.0     0.0     0.0
Heap     820.4   112.2   640.1    95.7  1668.4
Stack      8.2     1.1     6.3     0.9    16.5
Private  410.5    55.0   320.2    44.7   830.4

Qué significa: La memoria está distribuida entre nodos; dependiendo de la colocación de la CPU, algunos accesos son remotos.

Decisión: Considera ejecutar un grupo de workers por nodo NUMA, fijar conjuntos de CPU, o usar numactl para enlazar memoria en procesos calientes.

Task 10: Observar presión en la cola de ejecución y cambios de contexto

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
 2  0      0 8123456  98124 9234560  0    0     3    17  680 1200 12  3 84  1  0
10  0      0 8119320  98124 9235104  0    0     0     0 2200 9000 55 10 34  1  0
18  1      0 8101000  98124 9238000  0    0     0   420 3500 15000 60 15 20  5  0

Qué significa: r (en ejecución) es alto; cs (cambios de contexto) se dispara. Eso suele ser sobre-suscripción o contención de locks, no “necesitamos más núcleos.”

Decisión: Reduce conteos de hilos, inspecciona locks, ajusta pools de workers o fija hilos calientes. Comprar núcleos no es la primera solución.

Task 11: Confirmar que iowait no se hace pasar por limitación de CPU

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

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          22.10    0.00    6.90   18.40    0.00   52.60

Device            r/s     w/s   rkB/s   wkB/s  await  aqu-sz  %util
nvme0n1         120.0   880.0  7680.0 90240.0  12.4    9.20   96.0

Qué significa: Alto %iowait, alta %util del dispositivo y cola creciente (aqu-sz) indican que el almacenamiento es el limitador.

Decisión: Deja de culpar a los núcleos. Arregla almacenamiento: reduce amplificación de escritura, aumenta el throughput, añade cache o escala el rendimiento de almacenamiento.

Task 12: Comprobar distribución de IRQ (la clásica mentira de “CPU alta”)

cr0x@server:~$ cat /proc/interrupts | head -n 8
           CPU0       CPU1       CPU2       CPU3
  24:   9123456          0          0          0   IO-APIC   24-fasteoi   nvme0q0
  25:         0          0          0          0   IO-APIC   25-fasteoi   nvme0q1
  26:         0          0          0          0   IO-APIC   26-fasteoi   nvme0q2
  27:         0          0          0          0   IO-APIC   27-fasteoi   nvme0q3

Qué significa: IRQs acumulándose en CPU0 pueden crear puntos calientes artificiales y latencia. El dispositivo es “multi-queue”, pero las interrupciones no están balanceadas.

Decisión: Habilita/verifica irqbalance, configura afinidad de interrupciones y vuelve a comprobar la latencia cola antes de tocar el conteo de núcleos.

Task 13: Ver si estás siendo estrangulado por cgroups (contenedores)

cr0x@server:~$ cat /sys/fs/cgroup/cpu.stat 2>/dev/null || cat /sys/fs/cgroup/cpu/cpu.stat
usage_usec 932112345
user_usec  701223000
system_usec 230889345
nr_periods  14400
nr_throttled 3920
throttled_usec 412334500

Qué significa: Mucho throttling (nr_throttled) y tiempo throttled significativo: no estás “sin núcleos”, estás sin cuota.

Decisión: Aumenta el límite de CPU, elimina límites para servicios críticos en latencia o redimensiona requests/limits y el tamaño de nodos.

Task 14: Comparar “tiempo CPU” vs “tiempo real” para detectar contención

cr0x@server:~$ /usr/bin/time -v bash -c 'python3 - <

Qué significa: Porcentaje de CPU cercano a 100% y tiempo real igual al tiempo de usuario sugiere ejecución limpia en CPU. Si el tiempo real es mucho mayor, estás esperando—a menudo en locks o I/O.

Decisión: Si el tiempo real se infla con concurrencia, investiga contención antes de comprar más núcleos.

Guía de diagnóstico rápido: encuentra el cuello de botella rápido

Cuando un sistema “debería ser más rápido porque tiene más núcleos” y no lo es, necesitas una ruta de triaje rápida y repetible.
No una semana de teatro de benchmarking.

Primero: prueba qué “núcleos” tienes en realidad

  1. Topología: lscpu para sockets/núcleos/hilos/nodos NUMA.
  2. Presión NUMA de memoria: numactl --hardware y numastat.
  3. Throttling: comprueba dmesg por eventos térmicos/energía; usa turbostat bajo carga representativa.

Si no puedes describir tu topología en una frase, no estás listo para interpretar gráficas de perf.

Segundo: determina si es CPU, memoria, almacenamiento o planificación

  1. Saturación de CPU vs contención: vmstat 1 (cola de ejecución r, cambios de contexto cs).
  2. Espera de I/O y saturación de dispositivo: iostat -xz 1.
  3. Puntos calientes de IRQ: /proc/interrupts y uso de colas NIC/NVMe.
  4. Throttling de cgroup: cpu.stat para tiempo throttled.

El objetivo: clasificar el cuello de botella. “La CPU está al 70%” no es una clasificación.

Tercero: valida con un experimento focalizado

  • Fija hilos (o deshabilita SMT durante una ventana de prueba) para ver si el rendimiento se vuelve más predecible.
  • Cambia la concurrencia (la mitad de los workers) para ver si el throughput se mantiene mientras mejora la latencia—firma clásica de contención.
  • Mueve la carga a una generación de CPU conocida y compara tiempo CPU por petición y latencia cola.

Un experimento, una hipótesis, un plan de rollback. Estás haciendo operaciones, no astrología.

Cita (idea parafraseada): La idea de John Ousterhout: mide y localiza el cuello de botella antes de optimizar—si no, solo estás cambiando código por diversión.

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

Esta es la parte que pegas en canales de incidentes cuando la gente empieza a corear “añadir más núcleos.”

1) Síntoma: “La CPU está baja pero la latencia es alta”

  • Causa raíz: throttling de cgroup, desbalance en la cola de ejecución o stalls de I/O. El CPU a nivel de nodo parece ocioso; tu pod está siendo asfixiado por cuota o esperando almacenamiento.
  • Solución: Revisa el throttling en cpu.stat, elimina límites para servicios críticos en latencia y valida la saturación de almacenamiento vía iostat.

2) Síntoma: “Servidor nuevo de más núcleos es más lento bajo carga”

  • Causa raíz: menor frecuencia sostenida con todos los núcleos, throttling térmico/energía o downclock por AVX.
  • Solución: Mide la frecuencia all-core con turbostat bajo carga representativa; ajusta límites BIOS y refrigeración; reduce concurrencia en secciones AVX si procede.

3) Síntoma: “El escalado se detiene en N hilos y luego empeora”

  • Causa raíz: contención de locks, bouncing de líneas de caché, saturación de ancho de banda de memoria o contención entre hermanos SMT.
  • Solución: Reduce conteo de hilos; fija a un hilo por núcleo; perfila locks; separa trabajo por nodo NUMA; considera deshabilitar SMT para esa clase de cargas.

4) Síntoma: “Instancia grande es más lenta que la pequeña para el mismo servicio”

  • Causa raíz: efectos NUMA y asignaciones remotas de memoria; el tráfico entre nodos aumenta la latencia cola.
  • Solución: Enlaza procesos y memoria con colocación consciente de NUMA; ejecuta múltiples instancias más pequeñas; o selecciona un SKU con menos dominios NUMA.

5) Síntoma: “Un núcleo está saturado; los demás están en reposo”

  • Causa raíz: afinidad de interrupciones/desbalance de IRQ, cuello de botella single-thread o un lock global.
  • Solución: Revisa /proc/interrupts; habilita irqbalance; arregla el cuello de botella single-thread; shardea el lock global; deja de asumir que “más núcleos” arregla trabajo serial.

6) Síntoma: “Actualizamos núcleos y ahora el almacenamiento empeoró”

  • Causa raíz: la etapa CPU se aceleró e incrementó la concurrencia de I/O, exponiendo límites de cola y amplificación de escritura en almacenamiento.
  • Solución: Limita la tasa de escritores, agrupa/coalesce I/O, ajusta queue depth, añade cache o escala el throughput de almacenamiento. Trata CPU y almacenamiento como un sistema acoplado.

Broma #2: Si dimensionas tu sistema solo por conteo de núcleos, básicamente estás eligiendo neumáticos según cuántas letras tiene la marca.

Listas de verificación / plan paso a paso

Checklist A: Antes de comprar “más núcleos”

  1. Define el objetivo: throughput, latencia mediana, latencia p99 o coste por petición. Elige uno primario.
  2. Recolecta evidencias reales del cuello de botella: cola de ejecución, iowait, throttling y utilización de almacenamiento.
  3. Captura la topología: sockets/núcleos/hilos/nodos NUMA y canales de memoria (al menos nodos NUMA y memoria libre por nodo).
  4. Verifica el modelo de licencias: núcleos físicos vs hilos; mínimos por socket; multiplicadores por familia CPU.
  5. Haz benchmarking realista: concurrencia representativa y mezcla de instrucciones; incluye cachés calientes; incluye red y almacenamiento cuando sea relevante.
  6. Decide el tipo de núcleo necesario: alto rendimiento single-thread vs muchos núcleos; riesgo de planificación por núcleos híbridos; valor de SMT.

Checklist B: Cuando el rendimiento es extraño después de una migración

  1. Verifica que no hay throttling: eventos térmicos y de potencia en logs; comprobación de frecuencia sostenida.
  2. Revisa throttling de cgroup: especialmente si está containerizado; confirma que los límites no cambiaron.
  3. Valida la colocación NUMA: pinning de CPU y localidad de memoria para los procesos más calientes.
  4. Comprueba balance de interrupciones: NIC y NVMe distribuyendo interrupciones entre CPUs.
  5. Compara tiempo CPU por petición: si el tiempo CPU por petición aumentó, estás en un núcleo más lento o haciendo más trabajo.
  6. Compara latencia de almacenamiento: “CPU más rápida” puede estar empujando más el almacenamiento; no confundas síntomas con causas.

Checklist C: Si debes comunicar esto a no ingenieros

  • Reemplaza “núcleos” por “trabajo hecho por segundo”. Vincúlalo a resultados de negocio (requests/sec con objetivo p99).
  • Usa un gráfico: throughput vs latencia bajo aumento de concurrencia. Expone contención y throttling rápido.
  • Explica NUMA como “distancia a la memoria”. La gente entiende distancia.
  • Explica SMT como “dos trabajadores compartiendo un mismo escritorio”. Es lo bastante preciso para evitar malas decisiones.

Preguntas frecuentes

1) ¿Son las vCPU lo mismo que los núcleos?

Usualmente no. vCPU comúnmente mapea a un hilo de hardware, no a un núcleo físico, y su rendimiento depende de la contención en el host y de la generación de CPU.
Trata el conteo de vCPU como una cuota de planificación y luego mide el throughput y la latencia reales.

2) ¿Debería desactivar SMT/Hyper-Threading?

No lo desactives por superstición. Prueba. Para algunas cargas críticas en latencia o con mucha contención de locks, deshabilitar SMT puede mejorar la latencia cola y la predictibilidad.
Para cargas de throughput con stalls, SMT puede ayudar. Hazlo por carga y por evidencias.

3) ¿Por qué una CPU con más núcleos a veces tiene peor rendimiento single-thread?

Porque los presupuestos de diseño son finitos: potencia, área de die, caché y frecuencia. Las CPUs optimizadas por densidad de núcleos pueden tener comportamiento de boost inferior,
caché por núcleo más pequeña o relojes sostenidos más bajos bajo carga.

4) ¿Cómo afectan P-cores/E-cores a servidores y contenedores?

Los diseños híbridos complican la planificación. Sin soporte correcto del kernel y de políticas, hilos sensibles a latencia pueden aterrizar en núcleos más lentos.
En contenedores, el pinning y los límites de CPU pueden amplificar errores de planificación. Valida con pinning consciente de topología y pruebas de latencia medidas.

5) ¿Cuál es la forma más rápida de saber si estoy limitado por CPU?

Busca alta utilización y bajo iowait, cambios de contexto modestos y una cola de ejecución acorde a expectativas.
Si iowait es alto o hay throttling, no estás “CPU-bound” en el sentido de que comprar más núcleos lo solucionará.

6) ¿Por qué el rendimiento empeora cuando aumento el número de hilos?

Contención. Más hilos pueden aumentar la competencia por locks, bouncing de líneas de caché, overhead del planificador y presión del ancho de banda de memoria.
Pasado cierto punto, la máquina gasta tiempo coordinando trabajo en lugar de ejecutarlo.

7) ¿Cómo aparece NUMA en los síntomas?

Signos típicos: picos en latencia p99 durante ráfagas, utilización desigual de CPU por nodo NUMA y rendimiento que empeora en máquinas “más grandes”.
Herramientas como numastat pueden mostrar asignaciones remotas; el pinning suele estabilizar el comportamiento.

8) ¿Son inútiles los datos de benchmarks de los proveedores?

No inútiles—solo incompletos. Los benchmarks del vendedor pueden indicar tendencias, pero los cuellos de botella de tu carga pueden ser distintos.
Usa los datos del proveedor para acotar opciones, luego valida con pruebas basadas en tus trazas o carga.

9) ¿Cómo evito sorpresas de licenciamiento por núcleo?

Trata el licenciamiento como una restricción técnica de primera clase. Antes de elegir una CPU, confirma qué cuenta como núcleo licenciado,
si SMT cuenta, si hay mínimos por socket y si aplican multiplicadores por familia CPU.

10) ¿Cuál es la métrica de “conteo de núcleos” más fiable para usar internamente?

Para discusiones de ingeniería: informa núcleos físicos, hilos SMT y nodos NUMA por separado. Para planificación de capacidad: usa “requests/sec con objetivo p99”
sobre un perfil de hardware definido. Esa es la métrica que sobrevive al marketing.

Conclusión: qué hacer a continuación

Deja de tratar el número en el nombre de la CPU como un SLA. “Más núcleos” es una capacidad, no una garantía—y a veces es una bomba presupuestaria con disipador.
Si operas sistemas en producción, tu trabajo es convertir sustantivos de marketing en realidad medida.

Pasos prácticos siguientes:

  1. Captura la topología para cada perfil de hardware que ejecutes: sockets, núcleos físicos, hilos SMT, nodos NUMA.
  2. Construye una pequeña suite de benchmarking repetible: una prueba de sanidad CPU, una prueba sensible a memoria, una prueba con almacenamiento en lazo y una reproducción de trazas si puedes.
  3. Para plataformas con contenedores, revisa rutinariamente el throttling de cgroups y el balance de IRQ antes de “escalar”.
  4. Al comprar hardware (o instancias), optimiza para el cuello de botella: latencia single-thread, ancho de banda de memoria, latencia de almacenamiento o coste de licencias—no el conteo de núcleos.

Haz eso, y “64 núcleos” volverá a ser una entrada de ingeniería con sentido—una que puedas usar sin despertarte a las 3 a.m.

← Anterior
Filtraciones IPv6 en Docker: evita la exposición “Ups, es pública”
Siguiente →
ZFS zpool initialize: Hacer que los discos nuevos funcionen mejor desde el primer día

Deja un comentario