...and with things like https://en.wikipedia.org/wiki/ExpEther , you can get even higher latencies.
What’s that law called about programmers wasting all the compute on abstraction?
E.g. we can build a board around a MC68000 where we make it lock up forever in a bus cycle, waiting for a DTACK that doesn't arrive.
Some early microprocessors had clocked bus cycles without handshaking. They would put out an address on some address lines and signal some line together with a read/write indication, and then expect the transfer to be completed within some clock cycles. If nothing is attached to the address, they would read whatever values are on the bus, like maybe all 1's if it is an open drain system that requires the transmitting device to pull to ground to indicate zero.
I'd say that kind of thing belongs to a hall of shame; it requires software hacks to interface with anything that can't keep up with the prescribed bus cycle.
It would be much more interesting to know the results if you're only allowed to use main memory.
> Trapped/emulated/virtualized instructions may only time the trap, not the handler.
But I feel like that 12ms write to an ACPI IO port at current leaderboard position 8 is probably trapping to SMM and being handled there.
I wonder what the actual limit on this `fxrstor64` is right now. If you can stall the PCIe bus for that long, then why not indefinitely? Certainly there's no forward progress guarantee here.

Instruction latency analysis usually focuses on performance
optimization—making code run as fast as possible. The Assembly Hall of Shame takes the opposite approach: searching for the absolute floor of
single-instruction performance.
Strategy: Use fxrstor64 to load 512-byte FPU/MMX/XMM state from a
high-latency MMIO region in the PCIe fabric, then starve the fabric while the
load is in flight — a fleet of hammer cores pounds a different high-latency
MMIO register with tight 4-byte reads, saturating the PCIe root complex and
endpoint with non-posted transactions, so CPU 0's 512-byte fxrstor64 must
queue behind all that contending traffic.
Contender: AMD Ryzen 7 5800H
; CPU 0 — timed instruction
movl $0xfcc68830, %rsi
fxrstor64 %rsi
; CPUs 1..N — hammer loop against a different high-latency location
movl 0xfcc68858, %eax
:trophy: Score: 198,002,498,236 cycles
:trophy: Time: 62 seconds
A spec-violating unaligned ymm0 load that forced non-posted dword transactions from stalled GPU registers was used to break the fundamental design of System Management Mode in smiiiiiiiiiiiiiiii.
vmovdqu 0xfcc003b1, %ymm0
rep movs, pause, etc. are
disqualified.Strategy: nop does nothing. It opens the leaderboard accordingly.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
nop
Score: 1 cycles
Time: 0 nanoseconds
Strategy: Regular nop was too short, but how do we make nothing take
longer? Try a lonnnnnng nop.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
data16 data16 data16 data16 data16 data16 data16 nopl 0x00000000(%%eax,%%eax,1)
Score: 20 cycles
Time: 7 nanoseconds
Strategy: Just a reference instruction to get our bearings.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
rdtsc
Score: 49 cycles
Time: 18 nanoseconds
Strategy: Use 128-bit dividend (rdx:rax=2:0) with small divisor to push the quotient above the ceiling imposed by sign-extension, driving the longest path through the divider microcode.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
xorq %rax, %rax ; rax = 0 (low 64 bits of dividend)
movq $2, %rdx ; rdx = 2 (high 64 bits: full dividend = 2^65)
movq $5, %rbx ; divisor → quotient = 2^65/5 ≈ 7.4×10^18
idivq %rbx
Score: 77 cycles
Time: 28 nanoseconds
Strategy: Use maximum nesting depth (31) to force 30 display-pointer loads and pushes through the microcode display-walk path.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
enter $0, $31 ; 0 bytes allocated, nesting depth 31 (maximum)
Score: 112 cycles
Time: 41 nanoseconds
Strategy: Try a small denormal to trigger an FP microcode assist.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
movabsq $0x0000000000000001, %rax
movq %rax, -8(%rsp)
fldl -8(%rsp)
Score: 133 cycles
Time: 49 nanoseconds
Strategy: Just ensure the cache line is dirty.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
clflush (%rax) ; rax -> dirty cache line resident in L3
Score: 165 cycles
Time: 60 nanoseconds
Strategy: Use exponent 0x7ff to reach 'special value' processing in microcode; positive/negative, NaN/inf doesn't seem to make a difference, go with QNaN.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
movabsq $0x7fffffffffffffff, %rax
movq %rax, -8(%rsp)
fldl -8(%rsp)
fsin
Score: 257 cycles
Time: 94 nanoseconds
Strategy: Saturate all write-combining line-fill buffers with movnti
stores to distinct cache lines, forcing mfence to drain the full LFB write
path to the uncore before retiring.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
movnti %r9, 0*64(%rdi) ; ×16 distinct cache lines — saturate the write-combining LFBs
; …
movnti %r9, 15*64(%rdi)
mfence ; must drain all pending LFB writes before retiring
Score: 326 cycles
Time: 120 nanoseconds
Strategy: Nothing for now, just check how long it takes to invalidate the TLB.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
mov %rax, %cr3
Score: 352 cycles
Time: 110 nanoseconds
Strategy: Hit x87 FP microcode assist path by using denormal source operand.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
fldl subnorm ; 1e-310: value < DBL_MIN, biased exponent = 0
faddl subnorm ; source is subnormal → FP microcode assist
Score: 677 cycles
Time: 249 nanoseconds
Strategy: Align lock-prefixed operand to straddle cache-line
boundary, forcing CPU to assert the external bus lock rather than using the fast
MESI cache-coherence path.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
; split_ptr % 64 == 63 — dword spans bytes 63 (line N) and 64–66 (line N+1)
lock xaddl %r9d, (%rdi)
Score: 865 cycles
Time: 319 nanoseconds
Strategy: Use subnormal divisor, hardware hands control to microcode assist, assist normalizes operand, performs the division, then restores architectural state.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
movabsq $0x3ff0000000000000, %rax ; 1.0 (normal dividend)
movq %rax, -8(%rsp)
fldl -8(%rsp) ; ST(0) = 1.0
movabsq $0x0000002000000000, %rax ; 6.79e-313 (subnormal divisor)
movq %rax, -8(%rsp)
fdivl -8(%rsp) ; ST(0) = 1.0 / subnormal → FP assist
Score: 883 cycles
Time: 325 nanoseconds
Strategy: Use rakefield to find the highest latency CPUID leaves.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
movl $6, %eax
cpuid
Score: 1248 cycles
Time: 460 nanoseconds
Strategy: Execute in a tight loop to deplete the hardware entropy pool faster than it can be refilled, forcing subsequent calls to stall while the entropy source recovers.
Contender: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
rdrand %rax
Score: 5,579 cycles
Time: 2.057 microseconds
Strategy: Use project:nightshyft to identify high latency MSRs. MCG_CTL on Zen look like a winner: may be a microcode quiesce and synchronize on MCA error banks across hardware units, some potentially off-die, requiring fabric-level communication rather than a simple local register write.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
movl $0x17b, %ecx ; MCG_CTL
wrmsr
Score: 34,304 cycles
Time: 10.742 microseconds
Strategy: Target an I/O port that straddles a NIC device register boundary, triggering the device to quiesce its TX DMA engine on each write.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
mov $0xf019, %dx
outl %eax, %dx
Score: 49,857 cycles
Time: 15.580 microseconds
Strategy: Use project:nightshyft to identify high latency model-specific-registers: VIA uses an undocumented register at 0x133 that gives wildly high response time. No idea what it does.
Contender: VIA Eden Processor 800MHz
movl $0x133, %ecx ; undocumented MSR
rdmsr
Score: 161,602 cycles
Time: 202.004 microseconds
Strategy: Fully load L1/L2/L3 caches with dirty lines to force DRAM writeback of entire hierarchy.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
wbinvd
Score: 1,616,480 cycles
Time: 506.165 microseconds
Strategy: Target I/O port mapped to an ACPI PM block where an unaligned 4-byte read decodes into multiple non-posted loads from wherever this port goes.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
mov $0x0413, %dx
inl %dx, %eax
Score: 12,524,415 cycles
Time: 3.921769 milliseconds
Strategy: Use mmiotic to identify high-latency deadspace in PCIe fabric, hit unkown GPU register.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
movl 0xfcc003b0, %esi
Score: 443,937,696 cycles
Time: 139.010268 milliseconds
Strategy: Search MMIO space for slowest registers in PCIe fabric, hit unknown GPU register, use 8-byte MMIO read to get two dword register accesses, which isn't technically allowed but works anyway.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
movq 0xfcc003b0, %rax
Score: 887,716,864 cycles
Time: 277.971228 milliseconds
Strategy: Search MMIO space for slowest registers in PCIe fabric, hit unknown GPU register, use 16-byte MMIO read to get four dword register accesses, which isn't technically allowed but works anyway.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
vmovdqu 0xfcc003b0, %xmm0
Score: 1,774,555,776 cycles
Time: 555.664133 milliseconds
Strategy: Search MMIO space for slowest registers in PCIe fabric, hit unknown GPU register, use 32-byte MMIO read to get eight dword register accesses, which still isn't technically allowed but works anyway.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
vmovdqu 0xfcc003b0, %ymm0
Score: 3,549,079,296 cycles
Time: 1.111345034 s
Strategy: Search MMIO space for slowest registers in PCIe fabric, hit unknown GPU register, use 32-byte unaligned MMIO read to get nine dword register accesses, which is even less allowed than the aligned version, but works anyway.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
vmovdqu 0xfcc003b1, %ymm0
Score: 4,453,212,256 cycles
Time: 1.394428818 seconds
Strategy: Use mmiotic to identify high-latency deadspace in PCIe fabric, isolate region near 0's and offset state to avoid MXCSR corruption (possibly VGA buffer?), use fxrstor64 to load 512-byte FPU/MMX/XMM state from MMIO, forcing CPU to process 512 bytes of I/O transactions through slowest available memory aperture.
Contender: AMD Ryzen 7 5800H
movl $0xfcc68830, %rsi
fxrstor64 %rsi
Score: 74,584,168,512 cycles
Time: 23.354502677 seconds
Strategy: Extend fxrstor64 (baseline) by starving the fabric while the load is in flight — a fleet of hammer cores pounds a different high-latency MMIO register with tight 4-byte reads, saturating the PCIe root complex and endpoint with non-posted transactions, so CPU 0's 512-byte fxrstor64 must queue behind all that contending traffic.
Contender: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5)
; CPU 0 — timed instruction
movl $0xfcc68830, %rsi
fxrstor64 %rsi
; CPUs 1..N — hammer loop against a different high-latency location
movl 0xfcc68858, %eax
:trophy: Score: 198,002,498,236 cycles
:trophy: Time: 62 seconds
Strategy: Leverage extended AVX state in Sapphire Rapids with MMIO approach
from fxrstor64: xsave state area is 8KB vs 512 bytes, 16x size ->
1,000,000,000,000 cycles
Contender: TODO
; XCR0 must enable AMX components (bits 17-18); state area ~8KB
xrstor64 (%rsi) ; rsi -> MMIO region, same technique as fxrstor64
The assembly hall-of-shame is a research effort from Christopher Domas (@xoreaxeaxeax).
There has been a ton of work to improve throughput, but that's often come at the cost of latency, because a great technique to improve throughput is batching, to avoid the per-task overhead cost.
We've also added many layers of abstraction.
A seminal example is Dan Luu's "computer latency" table (2017) https://danluu.com/input-lag/, which measures the time between a keypress and visible changes on the screen, and wherein an Apple IIe has latency 5x lower than a Lenovo X1 Carbon on Windows.
From some perspective, you could say that the Lenovo on Windows example is an impressive feat of engineering, considering all the subsystems involved (USB, interrupt dispatcher, input layer, windowing system, double-buffering...)
This throughput-over-latency tradeoff can be seen across the entire computer landscape design.
https://en.wikipedia.org/wiki/Metastability_(electronics)
Ultimately... failure modes must arise because naive gate design simulation models can't determine issues in a computationally feasible time frame.
The consequences of "fixing" CDC prone design flaws makes a processor many times slower (8 to 16 times slower on my dumb attempt), and develops weird alien design features very different from Von Neumann architectures.
This is why we can't have nice things. =3
Score: 1 cycles Time: 0 nanoseconds
If some app responds in 10ms or less, it is INTERACTIVE.
makes you think.
The actual typical hardware implementation just fetches the next 16-32 bytes from icache, shifts it to the correct alignment, and slams it into a bunch of parallel decoders which each attempts to decode one x86 instruction per byte.
The next cycle, the first 1-6 non-overlapping valid instructions are accepted into a queue for further decoding. The NOP almost certainly takes up space in this queue.
At no point does RIP get incremented by one. There isn't even a single physical RIP register to increment, the CPU is "executing" dozens or even hundreds of RIPs in parallel.
I looked it up and it is .1 seconds (100ms)
The basic advice regarding response times has been about the same for thirty years [Miller 1968; Card et al. 1991]:
- 0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.
- 1.0 second is about the limit for the user's flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no special feedback is necessary during delays of more than 0.1 but less than 1.0 second, but the user does lose the feeling of operating directly on the data.
- 10 seconds is about the limit for keeping the user's attention focused on the dialogue. For longer delays, users will want to perform other tasks while waiting for the computer to finish, so they should be given feedback indicating when the computer expects to be done. Feedback during the delay is especially important if the response time is likely to be highly variable, since users will then not know what to expect.
from Jakob Nielsen:
https://www.nngroup.com/articles/response-times-3-important-...
less readable but the original paper:
https://www.yusufarslan.net/sites/yusufarslan.net/files/uplo...
Humans can perceive much smaller latencies.
If you look at the Card & Miller reference, at least some humans can perceive differences in ~50ms vs 100ms latencies when typing (in my limited testing, it’s likely you can!). There’s some newer research I don’t have handy that I believe found error rates decreased and NSAT improved until around at least 30ms (if not 20ms).
On that note, humans can definitely distinguish 60hz vs 120hz reliably (about 8ms faster per frame).
Even faster: with a reference (eg when dragging on a touchscreen), humans can distinguish down to at least 1ms vs 10ms of latency: https://m.youtube.com/watch?v=vOvQCPLkPt4
And you can probably distinguish metronomes that are off by about 1-2ms. Much smaller for other things (like metronomes that slightly slower or faster than one another).
This is a special interest of mine XD