Pentium 4 / NetBurst: el error más sonoro de la era GHz

¿Te fue útil?

Si administraste sistemas en producción a principios de los años 2000, probablemente recuerdas la sensación: compraste “más GHz”,
tus gráficas no mejoraron y sí lo hizo tu pager. La latencia siguió grosera, el rendimiento por segundo se mantuvo plano y los ventiladores aprendieron
nuevas formas de chillar.

NetBurst (la microarquitectura del Pentium 4) es un caso de estudio sobre lo que ocurre cuando el marketing y la microarquitectura
se estrechan demasiado la mano. No es que los ingenieros no supieran lo que hacían. Es que las restricciones eran brutales,
la apuesta era estrecha y el mundo real no quiso cooperar.

La tesis: GHz era un proxy, no un producto

NetBurst se diseñó para frecuencia. No “frecuencia eficiente” ni “buena frecuencia”, sino “pon el número en la caja
y que el mundo lo discuta después”. Intel había pasado años entrenando a los clientes a interpretar la velocidad de reloj
como rendimiento. El mercado recompensó esa simplificación. Luego llegaron las facturas: pipelines de instrucciones tan largos
que las predicciones fallidas eran costosas, un subsistema de memoria que no podía seguir el ritmo y una densidad de potencia que convirtió
el diseño de rack en un pasatiempo para los nerds de HVAC.

Esto no fue una sola mala decisión de diseño. Fue un conjunto apilado de compensaciones que todas asumían una cosa:
los relojes seguirían subiendo y el software jugaría junto. Cuando cualquiera de esas suposiciones falló—código con muchas ramas, cargas pesadas en memoria,
restricciones realistas del datacenter—todo el enfoque se desplomó.

Si quieres la traducción SRE: NetBurst se optimizó para picos bajo microbenchmarks ideales y castigó la latencia de cola
bajo carga mixta de producción. Se puede enviar mucha decepción así.

Exactamente una vez vi una presentación de compras tratar “3.0 GHz” como si fuera un SLA de throughput.
Eso es como estimar el rendimiento de red contando las letras en “Ethernet”.

Internos de NetBurst: la tubería que se comió tu IPC

Canalizaciones profundas: geniales para frecuencia, terribles para errores

La historia clásica de NetBurst es “pipeline muy profundo”. La historia práctica es “alto coste por predicción fallida”.
Un pipeline más profundo te ayuda a alcanzar frecuencias más altas porque cada etapa hace menos trabajo. La desventaja es que ahora
has alargado la distancia entre “creímos la rama” y “descubrimos que estábamos equivocados”. Cuando estás equivocado, limpias mucho trabajo en vuelo y empiezas de nuevo.

Las CPUs modernas siguen teniendo pipelines profundos, pero lo compensan con predictores mejores, cachés más grandes, ejecución más ancha
y gestión de potencia cuidadosa. NetBurst se metió profundo temprano, con predictores y sistemas de memoria que no cubrían completamente
la apuesta en rutas de código típicas de servidor.

Trace cache: ingenioso, complejo y sensible a la carga

La trace cache de NetBurst almacenaba micro-ops (uops) decodificados, no instrucciones x86 crudas. Era inteligente: decodificar x86
no es trivial, y una uop cache puede reducir el coste del front-end. Pero también hizo el rendimiento más dependiente de cómo fluía y se alineaba el código.
Si tu flujo de instrucciones no encajaba bien—muchas ramas, distribución extraña, mala localidad—la trace cache dejó de ser un regalo y se convirtió en otro lugar donde fallar.

La idea no estaba mal; era temprana y frágil. Las uop caches de hoy funcionan porque el resto del sistema mejoró al alimentarlas, y porque
los trade-offs de potencia/rendimiento se gestionan con más delicadeza.

FSB y northbridge compartido: la caseta de peaje del ancho de banda

Los sistemas Pentium 4 dependían de un front-side bus (FSB) hacia un controlador de memoria separado (northbridge). Eso significa que tu
núcleo CPU es rápido, tu memoria está “en otro lugar” y cada petición es un viaje a través de un bus compartido. Bajo carga,
ese bus se convierte en un problema de planificación. Añade múltiples CPUs y se vuelve un proyecto en grupo.

Compáralo con diseños posteriores con controladores de memoria integrados (AMD lo hizo antes en x86; Intel después). Cuando
acercas la memoria y le das caminos más dedicados, reduces la contención y lowers la latencia. En producción, la latencia es moneda.
NetBurst la gastó como turista.

Era SSE2/SSE3: fuerte en cálculo en streaming, desigual en otros escenarios

NetBurst se comportaba bien en algunos workloads vectorizados y de streaming—código que podía procesar arrays de forma predecible y
evitar lógica con muchas ramas. Por eso los benchmarks podían verse bien si estaban diseñados para alimentar la máquina con el tipo
de trabajo que le gustaba. Pero los servicios reales no son tan educados. Analizan, ramifican, asignan, bloquean y esperan I/O.

NetBurst era el equivalente CPU de un motor ajustado para una pista específica. Mételo en tráfico urbano y aprenderás qué significa “curva de par”.

Por qué las cargas reales duelen: cachés, ramas, memoria y espera

IPC es lo que sientes; GHz es lo que presumes

Instrucciones por ciclo (IPC) es un proxy tosco pero útil para “cuánto trabajo se hace por tic”. NetBurst a menudo
tenía menor IPC que sus contemporáneos en muchas cargas de propósito general. Así que el chip corría a mayor frecuencia para
compensar. Eso puede funcionar—hasta que no, porque:

  • El código con muchas ramas dispara predicciones fallidas, que son más costosas en pipelines profundos.
  • Los fallos de caché paran la ejecución, y un núcleo rápido simplemente alcanza la parada antes.
  • La latencia FSB/memoria se convierte en un muro que no puedes atravesar con reloj.
  • La potencia/térmicos fuerzan throttling, así que los GHz prometidos son aspiracionales.

Predicción de ramas fallida: el impuesto de latencia que sigues pagando

Las cargas de servidor están llenas de ramas impredecibles: enrutamiento de peticiones, parsing, comprobaciones de autorización, búsquedas en hash tables,
llamadas virtuales, decisiones de compresión, rutas de ejecución de bases de datos. Cuando los predictores fallan, los pipelines profundos pierden
trabajo y tiempo. La CPU no “se ralentiza”. Simplemente hace menos trabajo útil mientras está muy ocupada.

Muro de memoria: cuando el núcleo va más rápido que el sistema

NetBurst podía ejecutar rápido cuando se le alimentaba, pero muchas cargas están limitadas por la memoria. Un fallo de caché son cientos
de ciclos de espera. Ese número no es un fallo moral; es física más topología. El efecto práctico es que una CPU con más GHz puede verse peor
si alcanza stalls de memoria más frecuentemente o no puede ocultarlos eficazmente.

Desde la perspectiva del operador, esto se manifiesta como: alta utilización de CPU, throughput mediocre y un sistema que
se siente “atascado” sin saturación obvia de I/O. No está atascado. Está esperando memoria y peleándose consigo mismo.

Ejecución especulativa: útil, pero amplifica el coste de las apuestas equivocadas

La especulación es cómo las CPUs modernas obtienen rendimiento: adivina una ruta, ejecútala y descártala si está equivocada. En un pipeline profundo,
la ruta equivocada es cara. La apuesta de NetBurst fue que mejores relojes pagarían por eso. A veces lo hicieron. A menudo, no.

Una de las lecciones operacionales más simples de la era NetBurst: no trates “CPU al 95%” como “CPU hace 95% de trabajo útil”.
Necesitas contadores, no sensaciones.

Térmicos y energía: cuando la CPU negocia con la física

La densidad de potencia se convirtió en una característica del producto (por accidente)

NetBurst se calentaba. Especialmente los Pentium 4 basados en Prescott, que se hicieron notorios por consumo y calor. El calor no es solo
una factura de electricidad; es riesgo de fiabilidad, ruido de ventiladores y variabilidad de rendimiento.

En producción, los mapas térmicos se convierten en mapas de incidentes. Si un diseño exige enfriamiento intenso, tu margen desaparece:
filtros polvorientos, un ventilador fallido, una rejilla bloqueada, un pasillo cálido que sube o un rack pegado a la pared se convierten en eventos de rendimiento.
Y los eventos de rendimiento se convierten en eventos de disponibilidad.

Térmico throttling: el freno invisible

Cuando una CPU reduce frecuencia por calor, el reloj cambia, la ejecución cambia y la latencia de cola de tu servicio se desplaza de maneras que tus pruebas de carga nunca modelaron.
Con sistemas de la era NetBurst, no era raro ver “el benchmark dice X” pero “prod hace Y” porque las condiciones ambientales no estaban controladas como en un laboratorio.

Broma #1: Prescott no era un reemplazo de calentador, pero hacía las guardias de invierno un poco más soportables si te sentabas cerca del rack.

Fiabilidad y operaciones: los sistemas calientes envejecen más rápido

Capacitores, VRMs, ventiladores y placas base no aman el calor. Incluso cuando sobreviven, se desvían. Ese desvío se convierte en errores intermitentes,
reinicios espontáneos y folklore de “funciona después de volver a conectar”. Eso no es misticismo; es expansión térmica, entrega de potencia marginal
y componentes fuera de su zona de confort.

Una idea parafraseada a menudo atribuida a W. Edwards Deming aplica claramente a ops: “No puedes gestionar lo que no mides.”
Con NetBurst tenías que medir térmicos, porque la CPU seguro que lo hacía.

Hyper-Threading: el truco bueno que expuso las malas suposiciones

Hyper-Threading (SMT) llegó a algunos modelos de Pentium 4 y fue legítimamente útil en las condiciones adecuadas:
podía llenar los huecos del pipeline ejecutando otro hilo cuando uno estaba estancado. Suena como rendimiento gratis,
y a veces lo era.

Cuando ayudaba

  • Cargas mixtas donde un hilo espera fallos de caché y el otro puede usar las unidades de ejecución.
  • Servicios con mucho I/O donde un hilo se bloquea frecuentemente y la sobrecarga del scheduler es manejable.
  • Algunos roles de servidor orientados al throughput con peticiones independientes y contención limitada de locks.

Cuando perjudicaba

  • Cargas limitadas por ancho de banda de memoria: dos hilos solo compiten más por el mismo cuello de botella.
  • Cargas con muchos locks: mayor contención, más rebote de líneas de caché, peor latencia de cola.
  • Servicios sensibles a latencia: jitter por recursos compartidos y artefactos de scheduling.

Hyper-Threading en NetBurst es un buen microcosmos de una regla general: SMT mejora diseños buenos y empeora diseños frágiles.
Puede aumentar el throughput mientras hace la latencia más fea. Si tu SLO es p99, no “actívalo y reza”. Haz pruebas A/B con concurrencia parecida a producción y revisa la cola.

Hechos históricos que importan (y algunos que todavía duelen)

  1. NetBurst debutó con Willamette (Pentium 4, 2000), priorizando velocidad de reloj sobre IPC.
  2. Northwood mejoró la eficiencia y las frecuencias, y se convirtió en el Pentium 4 “menos doloroso” para muchos compradores.
  3. Prescott (2004) pasó a un proceso más pequeño, añadió características y se hizo famoso por calor y consumo.
  4. La “carrera de GHz” moldeó las decisiones de compra tanto que “reloj más alto” a menudo ganó a mejor arquitectura en conversaciones de ventas.
  5. Acceso a memoria basado en FSB implicaba que la CPU competía por ancho de banda sobre un bus compartido hacia el northbridge.
  6. Trace cache almacenaba micro-ops decodificados, buscando reducir la sobrecarga de decodificación y alimentar eficientemente la larga pipeline.
  7. Hyper-Threading llegó en modelos selectos y podía mejorar throughput usando recursos de ejecución ociosos.
  8. Pentium M (derivado de la línea P6) a menudo superaba a Pentium 4 con relojes mucho más bajos, especialmente en tareas del mundo real.
  9. Intel finalmente pivotó lejos de NetBurst; Core (de otra línea) reemplazó la estrategia en lugar de iterarla indefinidamente.

Tres mini-historias corporativas desde las trincheras

Mini-historia 1: el incidente causado por una suposición equivocada (“GHz = capacidad”)

Una empresa mediana heredó una flota de servidores web envejecidos y planeó una renovación rápida. Los criterios de selección eran
dolorosamente simples: elegir las cajas Pentium 4 de mayor reloj dentro del presupuesto. La nota de compras literalmente equiparaba
“+20% de reloj” con “+20% de peticiones por segundo”. Nadie actuaba con malicia; estaban ocupados.

El despliegue fue fluido hasta que el tráfico alcanzó su pico normal. La utilización de CPU parecía bien—alta pero estable.
La red estaba bajo control. Los discos no gritaban. Sin embargo la latencia p95 subió y luego la p99 se disparó. El equipo on-call
hizo lo que hacen los equipos: reiniciaron servicios, movieron tráfico, culparon al balanceador y miraron gráficas hasta que las gráficas los miraron de vuelta.

El problema real fue el comportamiento de memoria. La carga había cambiado con los años: más personalización, más lógica de plantillas, más enrutamiento dinámico.
Eso significó más punteros encadenados y ramas. Los nuevos servidores tenían relojes más altos pero latencia de memoria similar y una topología FSB compartida
que empeoraba bajo concurrencia. Eran más rápidos llegando a los mismos stalls de memoria, y Hyper-Threading añadió contención en el peor momento.

La solución no fue “afinar Linux más”. La solución fue re-baselinear la capacidad usando una prueba parecida a producción:
concurrencia realista, fases de caché caliente y fría y latencia de cola como métrica de primera clase. La empresa terminó cambiando la mezcla de la flota:
menos cajas “reloj rápido”, más nodos balanceados con mejores subsistemas de memoria. También dejaron de usar GHz como número primario de capacidad.
Los milagros ocurren cuando dejas de mentirte a ti mismo.

Mini-historia 2: la optimización que salió mal (“usar HT para ganar rendimiento gratis”)

Otra compañía ejecutaba un servicio Java con muchas peticiones de corta duración. Activaron Hyper-Threading en toda la flota
y doblaron los hilos de trabajo, esperando ganancias lineales de throughput. Las pruebas sintéticas tempranas se veían geniales. Entonces llegaron
los informes de incidentes: picos de latencia esporádicos, pausas de GC alineándose con ráfagas de tráfico y un nuevo tipo de “está lento pero nada está al máximo”.

El sistema no estaba hambriento de CPU; estaba hambriento de caché y de locks. Dos CPUs lógicas compartían recursos de ejecución
y, más importante, caché compartida y rutas de ancho de banda de memoria. Los patrones de asignación y sincronización de la JVM
crearon rebotes de líneas de caché, y la mayor concurrencia amplificó la contención en hotspots que antes parecían inofensivos.

Intentaron arreglarlo aumentando el tamaño del heap, luego fijando hilos a CPUs, luego tocando perillas que se sentían “de sistemas”.
Algunas cosas ayudaron, la mayoría no. La verdadera mejora vino al dar un paso atrás: tratar Hyper-Threading como una herramienta de throughput con coste de latencia.
Mide el coste.

Revirtieron a menos hilos de trabajo, habilitaron HT solo en nodos que servían tráfico batch no interactivo y usaron perfiles de aplicación para eliminar un par de cuellos de botella de locks.
El throughput quedó ligeramente por encima de antes de la “optimización” y la latencia de cola volvió a ser aburrida. La lección no fue “HT es malo”.
La lección fue “HT es un multiplicador, y también multiplica tus errores”.

Mini-historia 3: la práctica aburrida pero correcta que salvó el día (“margen térmico es capacidad”)

Un equipo de servicios financieros ejecutaba trabajos nocturnos intensivos en cómputo en un clúster que incluía nodos Pentium 4 de la era Prescott.
A nadie le gustaban esas cajas, pero los trabajos eran estables y el clúster era “suficiente”. El superpoder silencioso del equipo era que trataban el entorno
como parte de la capacidad: monitorización de temperatura de entrada, chequeos de salud de ventiladores y alertas sobre indicadores de throttling térmico.

Un verano, una unidad de enfriamiento se degradó durante el fin de semana. No fue una caída total—solo rendimiento degradado. El lunes por la mañana
las duraciones de los trabajos subieron lentamente. La mayoría de equipos habría culpado al scheduler o a la base de datos. Este equipo notó una correlación sutil:
nodos en una fila mostraban lecturas térmicas ligeramente más altas y frecuencia efectiva de CPU ligeramente menor.

Vaciaron esos nodos, desplazaron trabajos a racks más fríos y abrieron un ticket con facilities con evidencia concreta.
También redujeron temporalmente la concurrencia por nodo para bajar la salida de calor y estabilizar los tiempos de ejecución. Sin drama, sin heroísmos,
sin sala de guerra a medianoche.

El resultado: los trabajos terminaron a tiempo, sin incidentes visibles al cliente, y el problema de enfriamiento se solucionó antes de que se convirtiera
en una fiesta de fallos de hardware. La práctica era aburrida—mide térmicos, vigila el throttling, mantiene margen—pero convirtió una “ralentización misteriosa”
en un cambio controlado. Lo aburrido está subestimado.

Tareas prácticas: 12+ comandos para diagnosticar “CPU rápida, sistema lento”

Estos son ejecutables en un servidor Linux típico. No tratas de “probar que NetBurst es malo” en 2026.
Aprendes a reconocer los mismos modos de fallo: stalls de pipeline, muro de memoria, artefactos de scheduling,
throttling térmico y utilización engañosa.

Tarea 1: Identificar la CPU y si HT está presente

cr0x@server:~$ lscpu
Architecture:            x86_64
CPU op-mode(s):          32-bit, 64-bit
CPU(s):                  2
Thread(s) per core:      2
Core(s) per socket:      1
Socket(s):               1
Model name:              Intel(R) Pentium(R) 4 CPU 3.00GHz
Flags:                   fpu vme de pse tsc ... ht ... sse2

Qué significa: “Thread(s) per core: 2” indica Hyper-Threading. El nombre del modelo te da la familia.

Decisión: Si HT está presente, haz benchmarks con HT activado/desactivado para servicios sensibles a latencia; no asumas que es una ganancia.

Tarea 2: Comprobar la frecuencia actual y el driver de escalado

cr0x@server:~$ grep -E 'model name|cpu MHz' /proc/cpuinfo | head
model name	: Intel(R) Pentium(R) 4 CPU 3.00GHz
cpu MHz		: 2793.000

Qué significa: La CPU no está a la frecuencia nominal. Podría ser ahorro de energía o throttling.

Decisión: Si la frecuencia está inesperadamente baja bajo carga, investiga governors y throttling térmico a continuación.

Tarea 3: Confirmar el governor de frecuencia de CPU

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

Qué significa: “ondemand” puede reducir la frecuencia hasta que la carga aumente; en plataformas antiguas puede responder lentamente.

Decisión: Para servicios de baja latencia, considera “performance” y vuelve a probar; para batch, “ondemand” puede estar bien.

Tarea 4: Buscar zonas térmicas y temperaturas

cr0x@server:~$ for z in /sys/class/thermal/thermal_zone*/temp; do echo "$z: $(cat $z)"; done
/sys/class/thermal/thermal_zone0/temp: 78000
/sys/class/thermal/thermal_zone1/temp: 65000

Qué significa: Las temperaturas están en miligrados Celsius. 78000 = 78°C.

Decisión: Si las temperaturas se acercan a umbrales de throttling durante picos, trata el enfriamiento como un limitador de capacidad, no como “trivia de facilities”.

Tarea 5: Detectar indicadores de throttling en logs del kernel

cr0x@server:~$ dmesg | grep -i -E 'throttl|thermal|critical|overheat' | tail
CPU0: Thermal monitoring enabled (TM1)
CPU0: Temperature above threshold, cpu clock throttled
CPU0: Temperature/speed normal

Qué significa: La CPU redujo velocidad por calor. Tu “misterio” de throughput puede ser física simple.

Decisión: Arregla flujo de aire/enfriamiento, reduce carga o reduce concurrencia. No ajustes software alrededor de un fallo térmico.

Tarea 6: Comprobar la cola de ejecución y saturación de CPU rápidamente

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 120000  15000 210000    0    0     2     5  900 1400 85 10  5  0  0
 4  0      0 118000  15000 209000    0    0     0     8 1100 1800 92  7  1  0  0

Qué significa: “r” (run queue) consistentemente por encima del número de CPUs implica contención de CPU. Bajo “id” significa ocupado.

Decisión: Si la run queue es alta, estás saturado de CPU o estancado. Siguiente: determina si es computación, memoria o locks.

Tarea 7: Identificar los principales consumidores de CPU y si están haciendo spin

cr0x@server:~$ top -b -n 1 | head -n 15
top - 12:14:01 up 21 days,  3:11,  1 user,  load average: 3.90, 3.60, 3.20
Tasks: 184 total,   2 running, 182 sleeping,   0 stopped,   0 zombie
%Cpu(s): 92.0 us,  7.0 sy,  0.0 ni,  1.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
2174 app      20   0  1856m  612m  122m R  98.7  7.6  12:11.02 java

Qué significa: Alta CPU en modo usuario puede seguir estando “esperando” (stalls de memoria, fallos de rama). “wa” bajo no despeja la CPU.

Decisión: Si un proceso domina, perfílalo; si muchos procesos comparten, sospecha contención sistémica o efectos del scheduler.

Tarea 8: Comprobar conmutaciones de contexto y presión de interrupciones

cr0x@server:~$ pidstat -w 1 5
Linux 6.1.0 (server) 	01/09/2026 	_x86_64_	(2 CPU)

12:14:20      UID       PID   cswch/s nvcswch/s  Command
12:14:21     1001      2174   1200.00    350.00  java

Qué significa: Conmutaciones de contexto muy altas pueden implicar demasiados hilos, contención de locks o churn de timers/IO.

Decisión: Si cswch/s es alto y la latencia es mala, reduce el número de hilos o arregla hotspots de locks antes de comprar hardware.

Tarea 9: Señales de estrés de ancho de banda de memoria vía perf (ciclos vs stalls frontend/backend)

cr0x@server:~$ sudo perf stat -p 2174 -e cycles,instructions,branches,branch-misses,cache-misses -a -- sleep 10
 Performance counter stats for 'system wide':

     32,100,000,000      cycles
     12,400,000,000      instructions              #    0.39  insn per cycle
      2,900,000,000      branches
        145,000,000      branch-misses             #    5.00% of all branches
        610,000,000      cache-misses

Qué significa: IPC bajo (0.39) junto con muchos fallos de caché/ramas sugiere que la CPU está ocupada pero no productiva.

Decisión: Optimiza caminos de código para localidad/predictibilidad de ramas, o elige una CPU con mejor IPC y manejo de memoria.

Tarea 10: Confirmar si realmente estás limitado por I/O

cr0x@server:~$ iostat -xz 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          90.50    0.00    7.20    0.10    0.00    2.20

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s  %util  await
sda              2.10    1.00   45.0    28.0     0.0     0.2    3.0    1.2

Qué significa: El disco está poco utilizado; await es bajo. Esto no es un cuello de botella de almacenamiento.

Decisión: Deja de culpar a los discos. Enfócate en CPU/memoria/locks y perfilado a nivel de petición.

Tarea 11: Revisar presión de memoria y paginación (el asesino silencioso del rendimiento)

cr0x@server:~$ free -m
               total        used        free      shared  buff/cache   available
Mem:            2048        1720         120          12         207         210
Swap:           2048         900        1148

Qué significa: Uso de swap puede estar bien, pero si hay paginación activa bajo carga verás stalls y picos.

Decisión: Si la actividad de swap correlaciona con latencia, reduce la huella de memoria, añade RAM o ajusta el emplazamiento de cargas.

Tarea 12: Verificar paginación activa, no solo uso de swap

cr0x@server:~$ sar -B 1 5
Linux 6.1.0 (server) 	01/09/2026 	_x86_64_	(2 CPU)

12:15:10  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgsteal/s
12:15:11      0.00      0.00    820.00      0.00   1200.00      0.00      0.00
12:15:12     10.00     45.00   2100.00     15.00    400.00    800.00    300.00

Qué significa: Fallos mayores (majflt/s) y escaneos indican presión real de memoria.

Decisión: Paginación bajo carga es un problema de capacidad. Arregla memoria, no flags de CPU.

Tarea 13: Inspeccionar la presión del scheduler de un vistazo

cr0x@server:~$ cat /proc/pressure/cpu
some avg10=12.34 avg60=10.01 avg300=8.55 total=987654321

Qué significa: CPU PSI “some” indica tiempo que las tareas pasan esperando recursos de CPU.

Decisión: Si PSI sube con la latencia, necesitas CPU más efectiva (IPC), menos threads ejecutables o degradación de carga.

Tarea 14: Detectar contención de locks (a menudo mal diagnosticada como “CPU lenta”)

cr0x@server:~$ sudo perf top -p 2174
Samples: 31K of event 'cpu-clock', 4000 Hz, Event count (approx.): 7750000000
Overhead  Shared Object        Symbol
  12.40%  libc.so.6            [.] pthread_mutex_lock
   9.10%  libjvm.so            [.] SpinPause

Qué significa: El tiempo se va en locking y spinning, no en trabajo productivo.

Decisión: Reduce la contención (shard locks, reduce threads, arregla secciones críticas calientes). Más GHz no te salvará.

Tarea 15: Validar la afinidad de caché mediante un microbenchmark rápido (no sustituye pruebas reales)

cr0x@server:~$ taskset -c 0 sysbench cpu --cpu-max-prime=20000 run
CPU speed:
    events per second:  580.21

General statistics:
    total time:                          10.0004s
    total number of events:              5804

Qué significa: Una prueba intensiva de cómputo puede verse “bien” incluso si tu servicio está limitado por memoria/ramas.

Decisión: Usa microbenchmarks solo para una comprobación de cordura; basa decisiones en tests representativos de la carga y latencia.

Broma #2: Si tu plan es “añadir hilos hasta que vaya rápido”, no estás optimizando—estás invocando demonios de contención.

Guía de diagnóstico rápido: qué comprobar primero/segundo/tercero

Este es el atajo de grado producción para sorpresas tipo NetBurst: sistemas que parecen “ricos en CPU” en papel pero actúan
lentos en cargas reales. Quieres el cuello de botella rápido, no un debate filosófico sobre microarquitectura.

Primero: verifica que la CPU que crees tener sea la que estás recibiendo

  1. Frecuencia bajo carga: comprueba /proc/cpuinfo MHz, el governor y dmesg por throttling.
  2. Térmicos: revisa zonas térmicas y el estado de ventiladores/flujo de aire vía la telemetría disponible.
  3. Virtualización: confirma que no estás limitado por cuotas de CPU o vecinos ruidosos (PSI, cgroups).

Objetivo: eliminar “la CPU literalmente no está corriendo a la velocidad esperada” en 5 minutos.

Segundo: determina si estás limitado por computación, memoria o contención

  1. Run queue y PSI: vmstat y /proc/pressure/cpu para espera de CPU.
  2. perf IPC: ciclos vs instrucciones; IPC bajo sugiere stalls/fallos.
  3. Señales de contención de locks: perf top, pidstat context switches, volcados de hilos de la aplicación.

Objetivo: clasificar el dolor. No puedes arreglar lo que no nombras.

Tercero: confirma que no es I/O ni paginación

  1. Disco: iostat -xz para utilización y await.
  2. Paginación: sar -B para fallos mayores y actividad de escaneo.
  3. Red: revisa drops/errores y colas (no mostrado arriba, pero deberías hacerlo).

Objetivo: dejar de perder tiempo en el subsistema equivocado.

Cuarto: decide si es un problema de encaje de hardware o de software

  • Si el IPC es bajo por fallos de caché y branch misses, necesitas mejor localidad o una CPU con mejor IPC—no más GHz.
  • Si domina la contención, reduce la concurrencia o rediseña los caminos calientes—mejorar hardware no arreglará código serializado.
  • Si hay throttling, arregla primero el enfriamiento y la entrega de potencia; de lo contrario cada otro cambio es ruido.

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

1) Síntoma: “La CPU está al límite, pero el throughput es mediocre”

Causa raíz: IPC bajo por fallos de caché, predicciones de rama o latencia de memoria; la CPU parece ocupada pero está estancada.

Solución: Usa perf stat para confirmar IPC bajo y altos fallos; luego optimiza para localidad, reduce pointer chasing y perfila los caminos calientes. Si vas a comprar hardware, prioriza IPC y subsistema de memoria, no reloj.

2) Síntoma: “Los picos de latencia aparecen solo en tardes calurosas / después de cambiar un ventilador”

Causa raíz: Throttling térmico o flujo de aire pobre causando caídas de frecuencia y jitter.

Solución: Confirma mediante dmesg y lecturas de zonas térmicas; remedia el enfriamiento, limpia filtros, verifica curvas de ventiladores y mantiene margen de temperatura de entrada. Trata los térmicos como dependencia de primer orden del SLO.

3) Síntoma: “Habilitamos Hyper-Threading y la p99 empeoró”

Causa raíz: Contención de recursos en unidades de ejecución/cachés compartidas, mayor contención de locks o saturación de ancho de banda de memoria.

Solución: Prueba A/B HT on/off con concurrencia parecida a producción; reduce hilos; arregla hotspots de locks; considera HT solo para cargas orientadas a throughput o I/O.

4) Síntoma: “Los microbenchmarks mejoraron, la producción se volvió más lenta”

Causa raíz: Los microbenchmarks son intensivos y predecibles; producción es ramificada y dependiente de memoria. Diseños tipo NetBurst recompensan lo primero y castigan lo segundo.

Solución: Mide con mezclas de peticiones realistas, fases de caché caliente/fría y latencia de cola. Incluye concurrencia, comportamiento del asignador y tamaños de datos realistas.

5) Síntoma: “El load average aumentó después de ‘optimizar’ añadiendo hilos”

Causa raíz: Sobre-suscripción y contención; más hilos ejecutables incrementan overhead de scheduling y locking.

Solución: Usa pidstat para medir context switches, perf top para símbolos de lock y reduce concurrencia. Añade paralelismo solo donde el trabajo es paralelo y el cuello de botella se mueve.

6) Síntoma: “Las actualizaciones de CPU no ayudaron a la base de datos”

Causa raíz: La carga está limitada por latencia de memoria o ancho de banda (fallos en buffer pool, pointer chasing en B-trees, cache misses).

Solución: Aumenta la tasa de aciertos de caché efectiva (índices, forma de consultas), añade RAM, reduce el working set y mide misses/IPC. No lances GHz contra un muro de memoria.

7) Síntoma: “Todo parece bien salvo pausas ocasionales y timeouts”

Causa raíz: Paginación, pausas de GC o picos de contención que no aparecen como utilización sostenida.

Solución: Revisa fallos mayores, PSI y métricas de pausa de la aplicación. Arregla presión de memoria y reduce la amplificación de cola (timeouts, reintentos, thundering herds).

Listas de verificación / plan paso a paso

Checklist A: Comprar hardware sin repetir el error NetBurst

  1. Define el éxito como latencia y throughput (p50/p95/p99 + RPS sostenido), no la velocidad de reloj.
  2. Mide proxies de IPC: usa perf en cargas representativas; compara ciclos/instrucciones y tasas de fallos.
  3. Modela comportamiento de memoria: tamaño del working set, tasas de acierto de caché, concurrencia esperada y necesidades de ancho de banda.
  4. Valida térmicos: prueba en rack, con temperatura ambiente realista y perfiles de ventiladores.
  5. Prueba impacto de SMT/HT: on/off, con conteos reales de hilos y seguimiento de latencia de cola.
  6. Prefiere sistemas balanceados: canales de memoria, tamaños de caché e interconexión importan tanto como los relojes de los cores.

Checklist B: Cuando un despliegue de “CPU más rápida” hace prod más lenta

  1. Confirma frecuencia y throttling (governor, temperaturas, dmesg).
  2. Compara perf IPC y tasas de fallos antes/después.
  3. Revisa conteos de hilos y context switching; revierte primero los cambios de “doblar hilos”.
  4. Valida presión de memoria y paginación; arregla fallos mayores inmediatamente.
  5. Busca regresiones de contención de locks introducidas por la nueva concurrencia.
  6. Si aún no está claro, captura un flame graph o artefacto de profiling y revísalo como una línea de tiempo de incidente.

Checklist C: Estabilizar latencia de cola en sistemas viejos, calientes y con persecución de frecuencia

  1. Reduce la concurrencia para que coincida con los cores (especialmente con HT) y observa el impacto en p99.
  2. Afina la afinidad de hilos solo si conoces tu topología; de lo contrario te puedes encerrar en una esquina.
  3. Mantén el governor de CPU consistente (a menudo “performance” para nodos críticos de latencia).
  4. Haz cumplir margen térmico: alerta por temperatura y eventos de throttling, no solo por utilización de CPU.
  5. Optimiza caminos calientes para localidad; elimina ramas impredecibles cuando sea posible.
  6. Introduce backpressure y timeouts razonables para evitar tormentas de reintentos.

Preguntas frecuentes

1) ¿Fue Pentium 4 realmente “malo” o solo malentendido?

Fue una apuesta estrecha. En cargas que coincidían con sus puntos fuertes (streaming, código predecible y alto apalancamiento de reloj),
podía rendir bien. En cargas mixtas de servidor, a menudo entregaba peor rendimiento real por vatio y por dólar que alternativas. “Malentendido” es generoso; “mal vendido” está más cerca.

2) ¿Por qué más GHz no se tradujo en más rendimiento?

Porque el rendimiento depende del trabajo útil por ciclo (IPC) y de con qué frecuencia te atas en memoria, ramas y contención.
NetBurst aumentó el conteo de ciclos pero a menudo redujo el trabajo útil por ciclo en cargas reales.

3) ¿Cuál es la lección operativa para sistemas modernos?

No aceptes una sola métrica de titular. Para CPUs es GHz; para almacenamiento es “IOPS”; para redes es “Gbps”.
Pregunta siempre: ¿bajo qué latencia, con qué concurrencia y con qué comportamiento de cola?

4) ¿Hyper-Threading “arregló” NetBurst?

Ayudó en throughput en algunos casos llenando ranuras de ejecución ociosas, pero no cambió los fundamentos:
penalizaciones por pipeline profundo, cuellos de botella de memoria y limitaciones térmicas. También podía empeorar la latencia de cola añadiendo contención.
Trátalo como un ajuste, no como un valor por defecto bueno.

5) ¿Por qué Pentium M a veces vencía a Pentium 4 con relojes mucho más bajos?

Pentium M (de la estirpe P6) enfatizaba IPC y eficiencia. En cargas con muchas ramas y sensibles a caché, un IPC más alto
junto con mejor eficiencia a menudo vence a la frecuencia bruta, especialmente cuando el reloj provoca throttling de potencia y térmico.

6) ¿Cómo puedo saber si mi carga está limitada por memoria en vez de por CPU?

Busca IPC bajo con muchos fallos de caché en perf, además de mejora limitada al añadir cores o subir frecuencia.
También verás plateau de throughput mientras la CPU se mantiene “ocupada”. Eso suele ser un muro de memoria o de contención.

7) ¿Es el throttling térmico lo suficientemente común como para importar?

En diseños que corren calientes y en datacenters reales, sí. Incluso throttling modesto crea jitter. El jitter se convierte en latencia de cola,
y la latencia de cola se convierte en incidentes cuando reintentos y timeouts amplifican la carga.

8) ¿Qué debo benchmarkear para evitar errores de la era GHz?

Mide el servicio real: mezcla de peticiones realista, tamaño de datos realista, concurrencia realista e informa p95/p99 de latencia además de throughput.
Añade una fase de caché fría y una ejecución sostenida lo suficientemente larga para calentar el sistema.

9) ¿Existen equivalentes modernos de la trampa NetBurst?

Sí. Cualquier vez que optimices una métrica pico a costa del comportamiento sistémico: frecuencias turbo sin presupuesto térmico, benchmarks de almacenamiento
que ignoran latencia de fsync o pruebas de red que ignoran pérdida de paquetes bajo carga. El patrón es el mismo: el pico gana en la presentación, la cola pierde al cliente.

Conclusión: qué hacer la próxima vez que te vendan GHz

NetBurst no es solo trivia retro de CPUs. Es una historia clara sobre incentivos, medición y el coste de apostar
a un solo número. Intel optimizó para frecuencia porque el mercado pagaba por frecuencia. Las cargas que importaban—
código con muchas ramas, sistemas pesados en memoria, racks con restricciones térmicas—enviaron la factura.

Los siguientes pasos prácticos son aburridos, y por eso funcionan:

  1. Define el rendimiento usando latencia de cola, no el pico de throughput y definitivamente no la velocidad de reloj.
  2. Instrumenta para cuellos de botella: contadores perf, PSI, métricas de paginación y señales térmicas/de throttling.
  3. Benchmarkea como en producción: concurrencia, tamaño de datos, comportamiento de caché, heat soak y mezclas de peticiones realistas.
  4. Trata los térmicos como capacidad: si la CPU hace throttling, tu arquitectura está “limitada por enfriamiento”. Acéptalo.
  5. Sospecha de “rendimiento gratis”: HT/SMT, concurrencia agresiva y micro-optimizaciones que ignoran la contención.

Si recuerdas solo una cosa: los relojes son un componente, no una garantía. El sistema es el producto. Operalo como tal.

← Anterior
Compartir SMB sobre VPN sin desconexiones: solucionar ‘La ruta de red no se encontró’ de verdad
Siguiente →
PostgreSQL vs SQLite en un VPS: la elección rápida sin remordimientos

Deja un comentario