← SEARCHABLE ARCHIVE
Assembly · 2026-08-15

¿Cómo se mide la optimización de rendimiento x86-64?

Validar uops, dependencias, cachés y predicción de saltos con perfiles y benchmarks

INTERACTIVE READING MODE →

¿Cómo se mide la optimización de rendimiento x86-64?

Este artículo se ha creado con fines didácticos. El rendimiento cambia con microarquitectura, energía y temperatura, jerarquía de memoria, SO y entrada. No convierta un ciclo fijo en regla universal.

Menos instrucciones no garantizan más velocidad. Una instrucción puede generar varios uops, las independientes pueden solaparse y un cache miss o una dependencia larga puede dominar el bucle. Optimizar es medir el cuello de botella, formular una hipótesis causal e intentar refutarla con un experimento controlado.

Latencia y throughput

Latencia es el tiempo hasta que una operación dependiente usa el resultado; throughput es la frecuencia de inicio de operaciones independientes.

; dependency chain
add rax, rbx
add rax, rcx
add rax, rdx

; independent
add r8, rbx
add r9, rcx
add r10, rdx

Los mismos tres add tienen caminos críticos distintos. El benchmark debe decir qué mide.

Cuellos de botella por niveles

NivelEjemplos
Front-endinstruction cache, decode, uop cache
Executionports, latencia, dependencias, divider
Memorycache/DRAM/TLB, store forwarding
Controlbranch misprediction, objetivos indirectos
Systempage fault, scheduler, locks, I/O

Líneas de fuente, número de instrucciones, bytes y saltos son indicios, no mediciones de tiempo. Confirme primero el hot path con wall time y profiler.

Localidad y distribución de saltos

Arrays contiguos aprovechan cache lines y prefetch. Leer un campo de estructuras grandes o hacer pointer chasing desperdicia ancho de banda y limita paralelismo. AoS→SoA o reducir working set puede superar a ASM.

Un salto casi siempre igual es predecible. Datos irregulares pueden favorecer cmov o máscaras, pero añaden trabajo y dependencias. Un benchmark aleatorio distinto del producto puede engañar.

Contrato del benchmark

Documente hipótesis, tamaños y distribución, prevención de dead-code elimination, setup incluido, cache frío/caliente e independencia. Registre CPU, microcode, compiler/options, ISA, LTO/PGO, seed, affinity, energía, temperatura, repeticiones, distribución y carga del SO. Use varios runs, no solo el mejor.

rdtsc no es un temporizador automático: importan out-of-order, serialización, migración e invariant TSC. Empiece con framework fiable y reloj monotónico.

Profiler, counters y compilador

El profiler localiza tiempo; los counters prueban hipótesis de cycles, branches, cache y TLB. Los eventos dependen de CPU y sufren multiplexing, skid y especulación. IPC solo no decide calidad.

Orden: referencia C/C++ correcta, salida Release, algoritmo/data layout, PGO/target/intrinsics y solo después ASM en un hot loop estrecho. Una función ASM separada puede perder inlining y optimización interprocedural.

Antes de medir, pruebe 0, 1, límites vectoriales, tamaños grandes, overflow, alignment, alias/overlap, especiales FP, fallback de funciones, sanitizer y unwind.

Resumen

El rendimiento x86-64 combina latencia, throughput, uops, recursos, dependencias, cache/TLB, predicción y ruido del sistema. Localice con perfil, valide una hipótesis precisa y conserve ASM solo cuando beneficio y mantenimiento sean reproducibles.

Fuentes oficiales