← SEARCHABLE ARCHIVE
Assembly · 2026-08-15

如何测量 x86-64 性能优化?

用 profiler 与 benchmark 验证 uop、依赖、缓存与分支预测

INTERACTIVE READING MODE →

如何测量 x86-64 性能优化?

本文以教学为目的。 性能会随 microarchitecture、电力与温度、内存层级、OS、输入而变化,不要把固定 cycle 数当成普遍规则。

指令少不保证更快。一条指令可能拆成多个 uop,独立指令可以重叠执行,而一次 cache miss 或长 dependency 就可能主宰整个循环。优化是测量瓶颈、建立因果假设,再用受控实验尝试反证的过程。

latency 与 throughput

latency 是结果可供依赖指令使用前的延迟;throughput 是可开始独立运算的频率。

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

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

同样三个 add 有不同 critical path。benchmark 必须说明测的是哪一种。

多层瓶颈

层例子
Front-endinstruction cache、decode、uop cache
Executionport、latency、dependency、divider
Memorycache/DRAM/TLB、store forwarding
Controlbranch misprediction、indirect target
Systempage fault、scheduler、lock、I/O

源码行数、指令数、binary bytes、jmp 数都只是线索,不是时间证明。先用 wall time 与 profiler 确认 hot path。

locality 与分支分布

连续数组有利 cache line 与 prefetch。大结构只读一个 field 或 pointer chasing 会浪费带宽、限制 memory-level parallelism。AoS 改 SoA、缩小 working set 可能比 ASM 更有效。

几乎总往同方向的分支很好预测。无规律输入可能让 cmov 或 mask 有利,但也可能执行两边工作、增加 dependency。与产品分布不同的随机 benchmark 会误导。

benchmark 契约

记录假设、输入大小与分布、避免 dead-code elimination、是否包含 setup、cold/warm cache、重复是否独立。再记录 CPU、microcode、compiler/options、target ISA、LTO/PGO、seed、affinity、电源、温度、重复次数、结果分布、OS 负载。看多次独立 run,而非单一最好值。

rdtsc 不是自动的函数计时器;out-of-order、serialization、migration、invariant TSC 都必须处理。先使用可信 benchmark framework 与 monotonic clock。

profiler、counter 与 compiler

sampling profiler 找到时间位置;hardware counter 帮助检查 cycles、branch、cache/TLB 假设。但 event 意义依 CPU 而异,也有 multiplexing、skid、speculation。IPC 一个数字不能判定好坏。

优化顺序:建立正确的 C/C++ 基准与测试、查看 Release output、改善 algorithm/data layout、考虑 PGO/target/intrinsic,最后才在狭窄 hot loop 实验 ASM。独立 ASM 函数可能失去 inlining 与跨函数优化。

速度比较前必须测试 0、1、vector 边界、大输入、overflow、alignment、alias/overlap、FP 特殊值、feature fallback、sanitizer 与 unwind。

总结

x86-64 性能由 latency、throughput、uop、执行资源、dependency、cache/TLB、branch 预测与系统噪声共同决定。用 profiler 找 hot path,以明确假设的 benchmark 验证,只在收益与维护条件可重现的狭窄区域保留 handwritten ASM。

官方资料