Performance Hints
abseil.io
Performance Hints
1–10 of 46 posts
Re: Performance Hints
#2 L1 cache reference 2,000,000,000 ops/sec
L2 cache reference 333,333,333 ops/sec
Branch mispredict 200,000,000 ops/sec
Mutex lock/unlock (uncontended) 66,666,667 ops/sec
Main memory reference 20,000,000 ops/sec
Compress 1K bytes with Snappy 1,000,000 ops/sec
Read 4KB from SSD 50,000 ops/sec
Round trip within same datacenter 20,000 ops/sec
Read 1MB sequentially from memory 15,625 ops/sec
Read 1MB over 100 Gbps network 10,000 ops/sec
Read 1MB from SSD 1,000 ops/sec
Disk seek 200 ops/sec
Read 1MB sequentially from disk 100 ops/sec
Send packet CA->Netherlands->CA 7 ops/secRe: Performance Hints
#3Re: Performance Hints
#4Some of this can be reduced to a trivial form, which is to say practiced in reality on a reasonable scale, by getting your hands on a microcontroller. Not RTOS or Linux or any of that, but just a microcontroller without an OS, and learning it and learning its internal fetching architecture and getting comfortable with timings, and seeing how the latency numbers go up when you introduce external memory such as SD Card…
A lot of code can be pessimized by golfing instruction counts, hurting instruction-level parallelism and microcode optimizations by introducing false data dependencies.
Compilers outperform humans here almost all the time.
Re: Performance Hints
#5This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…
Re: Performance Hints
#6Some of this can be reduced to a trivial form, which is to say practiced in reality on a reasonable scale, by getting your hands on a microcontroller. Not RTOS or Linux or any of that, but just a microcontroller without an OS, and learning it and learning its internal fetching architecture and getting comfortable with timings, and seeing how the latency numbers go up when you introduce external memory such as SD Card…
Just be careful not to blindly apply the same techniques to a mobile or desktop class CPU or above. A lot of code can be pessimized by golfing instruction counts, hurting instruction-level parallelism and microcode optimizations by introducing false data dependencies. Compilers outperform humans here almost all the time.
Compilers make mistakes too and they can output very erroneous code. But that’s a different topic.
Re: Performance Hints
#7This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…
If the reciprocal numbers are more intuitive for you you can still say an L1 cache reference takes 1/2,000,000,000 sec. It's "ops/sec" that makes it look like it's a throughput.
An interesting thing about the latency numbers is they mostly don't vary with scale, whereas something like the total throughput with your SSD or the Internet depends on the size of your storage or network setups, respectively. And aggregate CPU throughput varies with core count, for example.
I do think it's still interesting to think about throughputs (and other things like capacities) of a "reference deployment": that can affect architectural things like "can I do this in RAM?", "can I do this on one box?", "what optimizations do I need to fix potential bottlenecks in XYZ?", "is resource X or Y scarcer?" and so on. That was kind of done in "The Datacenter as a Computer" (https://pages.cs.wisc.edu/~shivaram/cs744-readings/dc-comput... and https://books.google.com/books?id=Td51DwAAQBAJ&pg=PA72#v=one... ) with a machine, rack, and cluster as the units. That diagram is about the storage hierarchy and doesn't mention compute, and a lot has improved since 2018, but an expanded table like that is still seems like an interesting tool for engineering a system.
Re: Performance Hints
#8This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…
The reason why that formatting is not used is because it’s not useful nor true. The table in the article is far more relevant to the person optimizing things. How many of those I can hypothetically execute per second is a data point for the marketing team. Everyone else is beholden to real world data sets and data reads and fetches that are widely distributed in terms of timing.
Re: Performance Hints
#9Re: Performance Hints
#10This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…
Both ops/sec and sec/op vary on clock rate, and clock rate varies across machines, and along the execution time of your program.
AFAIK, Cycles (a la _rdtsc) is as close as you can get to a stable performance measurement for an operation. You can compare it on chips with different clock rates and architectures, and derive meaningful insight. The same cannot be said for op/sec or sec/op.