{"id":"numbers-to-know","title":"Numbers to know","sections":[{"id":"overview","title":"Overview","html":"<p>Suppose an interviewer asks: \"How long does it take to read 1 GB from an SSD?\" You don't need a benchmark to answer. If you remember that reading 1 MB in sequence from an SSD takes about 1 ms, then 1 GB, which is 1,000 MB, takes about 1,000 ms, or one second. The same read from a spinning hard disk takes about 20 seconds, and from main memory about a quarter of a second. Those three answers already tell you a lot about where a design should keep its hot data.</p>\n<p>Estimates like this come up all the time in design work. You might need to know how long it takes to generate 100 image thumbnails from disk, how much memory a data structure will take, or whether a link is fast enough to copy a backup overnight. Each of these needs only a few numbers that you know by heart, plus some careful arithmetic. This chapter collects those numbers in one place: powers of two, the classic latency table, throughput figures, and a few numbers for AI systems. The method for using them, step by step, is in <a href=\"/learn/estimation\">Back-of-the-envelope estimation</a>.</p>\n<p>A word on age. The famous latency table dates from around 2009 to 2012. Some of its rows have hardly moved since then, and others have improved more than tenfold. This chapter keeps the classic table as it was, because people still quote it, and then shows a modern ballpark next to it, with a source and a year for each number.</p>","headings":[]},{"id":"powers-of-two","title":"Powers of two","html":"<h3 id=\"powers-of-two\">Powers of two</h3>\n<p>Computers count in binary, so sizes and limits tend to land on powers of two. A few of them are worth knowing on sight.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Power</th><th>Exact value</th><th>Approximate value</th><th>Bytes</th></tr></thead><tbody><tr><td>2^7</td><td>128</td><td></td><td></td></tr><tr><td>2^8</td><td>256</td><td></td><td></td></tr><tr><td>2^10</td><td>1,024</td><td>1 thousand</td><td>1 KB</td></tr><tr><td>2^16</td><td>65,536</td><td></td><td>64 KB</td></tr><tr><td>2^20</td><td>1,048,576</td><td>1 million</td><td>1 MB</td></tr><tr><td>2^30</td><td>1,073,741,824</td><td>1 billion</td><td>1 GB</td></tr><tr><td>2^32</td><td>4,294,967,296</td><td></td><td>4 GB</td></tr><tr><td>2^40</td><td>1,099,511,627,776</td><td>1 trillion</td><td>1 TB</td></tr><tr><td>2^50</td><td>1,125,899,906,842,624</td><td>1 quadrillion</td><td>1 PB</td></tr></tbody></table></div>\n<p>Read the table like this. Each step of 10 in the power multiplies the value by 1,024, which is close to 1,000. So 2^10 is about a thousand, 2^20 about a million, 2^30 about a billion and 2^40 about a trillion.</p>\n<p>Two rows are worth remembering for their own sake:</p>\n<ul>\n<li><strong>2^8 = 256</strong> is the number of different values one byte can hold (0 to 255).</li>\n<li><strong>2^32 ≈ 4.3 billion</strong> is the number of different values a 32-bit unsigned integer can hold. If you plan to give every user, photo or event an ID, and you expect more than about 4 billion of them, a 32-bit ID will run out. A 64-bit ID holds about 1.8 × 10^19 values, which is enough for almost anything.</li>\n</ul>\n<h4 id=\"decimal-and-binary-units\">Decimal and binary units</h4>\n<p>The \"Bytes\" column above uses the same names for two different things. In everyday use, a <strong>kilobyte (KB)</strong> can mean either 1,000 bytes or 1,024 bytes, and a gigabyte can mean either 10^9 bytes or 2^30 bytes.</p>\n<p>To remove the confusion, the International Electrotechnical Commission (IEC) approved separate names for the binary sizes in December 1998, according to <a href=\"https://physics.nist.gov/cuu/Units/binary.html\" target=\"_blank\" rel=\"noopener noreferrer\">NIST's page on binary prefixes</a>:</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Decimal (SI) unit</th><th>Size</th><th>Binary (IEC) unit</th><th>Size</th></tr></thead><tbody><tr><td>kilobyte, kB</td><td>10^3 = 1,000 bytes</td><td>kibibyte, KiB</td><td>2^10 = 1,024 bytes</td></tr><tr><td>megabyte, MB</td><td>10^6 = 1,000,000 bytes</td><td>mebibyte, MiB</td><td>2^20 = 1,048,576 bytes</td></tr><tr><td>gigabyte, GB</td><td>10^9 bytes</td><td>gibibyte, GiB</td><td>2^30 = 1,073,741,824 bytes</td></tr><tr><td>terabyte, TB</td><td>10^12 bytes</td><td>tebibyte, TiB</td><td>2^40 bytes</td></tr></tbody></table></div>\n<p>The gap between the two grows with size. A KiB is 2.4% bigger than a kB. A MiB is 4.9% bigger than an MB, a GiB 7.4% bigger than a GB, a TiB 10% bigger than a TB, and a PiB about 12.6% bigger than a PB.</p>\n<p>When does it matter?</p>\n<ul>\n<li><strong>In estimates, it almost never matters.</strong> Your assumptions about users and object sizes are rarely within 10% of the truth. Use powers of ten, because the arithmetic is easier.</li>\n<li><strong>It matters when you compare quoted figures.</strong> Disk makers and network vendors use decimal units. Operating systems and memory sizes often use binary ones. For example, a hard-disk datasheet from Seagate lists one drive's top transfer rate as \"285 MB/s / 272 MiB/s\": the same speed in both units. A \"1 TB\" disk shows up as about 931 GiB in an operating system that counts in binary, and nothing is missing.</li>\n<li><strong>It matters when you set hard limits.</strong> If a field, a buffer or a quota must hold exactly 64 KiB, write 65,536 bytes in the code. 64,000 bytes is about 2% short.</li>\n</ul>\n<h4 id=\"quick-conversions\">Quick conversions</h4>\n<p>These are the conversions people use most in estimates. The \"shortcut\" column is the rounded number you do arithmetic with.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Quantity</th><th>Exact or close</th><th>Shortcut</th></tr></thead><tbody><tr><td>Seconds in a day</td><td>86,400</td><td>about 10^5</td></tr><tr><td>Seconds in a 30-day month</td><td>2,592,000</td><td>about 2.6 million, or 2.5 × 10^6</td></tr><tr><td>Seconds in a year</td><td>31,536,000</td><td>about 3 × 10^7</td></tr><tr><td>1 million requests a day</td><td>11.6 a second</td><td>about 12 a second</td></tr><tr><td>1 billion requests a day</td><td>11,574 a second</td><td>about 10^4 a second</td></tr><tr><td>1 Gbps (gigabit per second)</td><td>125 MB/s</td><td>about 100 MB/s after protocol overhead</td></tr><tr><td>Bits to bytes</td><td>divide by 8</td><td></td></tr></tbody></table></div>\n<p>Two quick checks show how the shortcuts work. If a service gets 100 million requests a day, divide by 10^5 to get about 1,000 requests a second on average. If a server writes 1 KB per request at 1,000 requests a second, that is 1 MB a second, or about 86 GB a day.</p>","headings":[{"id":"powers-of-two","title":"Powers of two","depth":3},{"id":"decimal-and-binary-units","title":"Decimal and binary units","depth":4},{"id":"quick-conversions","title":"Quick conversions","depth":4}]},{"id":"latency-numbers-every-programmer-should-know","title":"Latency numbers every programmer should know","html":"<h3 id=\"latency-numbers-every-programmer-should-know\">Latency numbers every programmer should know</h3>\n<p><strong>Latency</strong> is how long one operation takes from start to finish. The table below lists the latency of common operations, from reading a CPU cache to sending a packet across an ocean. The list was first compiled by Peter Norvig, in the answers section of his essay <a href=\"https://norvig.com/21-days.html#answers\" target=\"_blank\" rel=\"noopener noreferrer\">Teach Yourself Programming in Ten Years</a>. Jeff Dean of Google then updated it and showed it in his talks, under the title \"Numbers Everyone Should Know\". Jonas Bonér's <a href=\"https://gist.github.com/jboner/2841832\" target=\"_blank\" rel=\"noopener noreferrer\">gist of the table</a>, labelled \"~2012\", is the version most people copy.</p>\n<p>Units: 1 ns (nanosecond) = 10^-9 seconds. 1 µs (microsecond) = 10^-6 seconds = 1,000 ns. 1 ms (millisecond) = 10^-3 seconds = 1,000 µs = 1,000,000 ns.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Operation</th><th align=\"right\">ns</th><th align=\"right\">µs</th><th align=\"right\">ms</th><th>Notes</th></tr></thead><tbody><tr><td>L1 cache reference</td><td align=\"right\">0.5</td><td align=\"right\"></td><td align=\"right\"></td><td></td></tr><tr><td>Branch mispredict</td><td align=\"right\">5</td><td align=\"right\"></td><td align=\"right\"></td><td></td></tr><tr><td>L2 cache reference</td><td align=\"right\">7</td><td align=\"right\"></td><td align=\"right\"></td><td>14 × L1 cache</td></tr><tr><td>Mutex lock/unlock</td><td align=\"right\">25</td><td align=\"right\"></td><td align=\"right\"></td><td></td></tr><tr><td>Main memory reference</td><td align=\"right\">100</td><td align=\"right\"></td><td align=\"right\"></td><td>14 × L2 cache, 200 × L1 cache</td></tr><tr><td>Compress 1 KB with Zippy</td><td align=\"right\">3,000</td><td align=\"right\">3</td><td align=\"right\"></td><td></td></tr><tr><td>Send 1 KB over a 1 Gbps network</td><td align=\"right\">10,000</td><td align=\"right\">10</td><td align=\"right\"></td><td></td></tr><tr><td>Read 4 KB randomly from SSD</td><td align=\"right\">150,000</td><td align=\"right\">150</td><td align=\"right\"></td><td>assumes an SSD that reads about 1 GB/s</td></tr><tr><td>Read 1 MB sequentially from memory</td><td align=\"right\">250,000</td><td align=\"right\">250</td><td align=\"right\"></td><td></td></tr><tr><td>Round trip within the same data center</td><td align=\"right\">500,000</td><td align=\"right\">500</td><td align=\"right\">0.5</td><td></td></tr><tr><td>Read 1 MB sequentially from SSD</td><td align=\"right\">1,000,000</td><td align=\"right\">1,000</td><td align=\"right\">1</td><td>about 1 GB/s SSD; 4 × memory</td></tr><tr><td>HDD seek</td><td align=\"right\">10,000,000</td><td align=\"right\">10,000</td><td align=\"right\">10</td><td>20 × data center round trip</td></tr><tr><td>Read 1 MB sequentially over a 1 Gbps network</td><td align=\"right\">10,000,000</td><td align=\"right\">10,000</td><td align=\"right\">10</td><td>40 × memory, 10 × SSD</td></tr><tr><td>Read 1 MB sequentially from HDD</td><td align=\"right\">20,000,000</td><td align=\"right\">20,000</td><td align=\"right\">20</td><td>80 × memory, 20 × SSD</td></tr><tr><td>Send a packet California → Netherlands → California</td><td align=\"right\">150,000,000</td><td align=\"right\">150,000</td><td align=\"right\">150</td><td></td></tr></tbody></table></div>\n<p>A few terms, in case they are new:</p>\n<ul>\n<li>An <strong>L1 cache</strong> and an <strong>L2 cache</strong> are small, fast memories inside the CPU. L1 is the smallest and fastest. Main memory (RAM) sits outside the CPU and is much slower to reach.</li>\n<li>A <strong>branch mispredict</strong> happens when the CPU guesses which way an <code>if</code> will go, starts work on that path, and has to throw the work away because it guessed wrong.</li>\n<li>A <strong>mutex</strong> is a lock that lets only one thread at a time into a section of code.</li>\n<li><strong>Zippy</strong> was Google's internal name for a fast compression library, released as open source in 2011 under the name Snappy.</li>\n<li>An <strong>HDD seek</strong> is the time a hard disk takes to move its read head to the right track.</li>\n<li><strong>Sequential</strong> means reading bytes that sit next to each other. <strong>Random</strong> means jumping to a new place for each read.</li>\n</ul>\n<p>Different versions of the table disagree on a few rows. The version above follows Jeff Dean's slide from his October 2009 LADIS keynote, <a href=\"https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">Designs, Lessons and Advice from Building Large Distributed Systems</a>, and the jboner gist. An older slide from Dean's Stanford talk, <a href=\"https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">Software Engineering Advice from Building Large-Scale Distributed Systems</a>, gave slower numbers: 100 ns for a mutex, 10 µs to compress 1 KB with Zippy, and 30 ms to read 1 MB from disk. The row for reading 1 MB over a 1 Gbps network comes from that older slide. It checks out: 1 MB is 8 million bits, which takes 8 ms at 1 Gbps, so \"about 10 ms\" is fair.</p>\n<p>The table was also drawn as a <a href=\"https://i.imgur.com/k0t1e.png\" target=\"_blank\" rel=\"noopener noreferrer\">picture of grids of squares</a>, one square per unit of time, which makes the jumps between rows easy to see. Colin Scott's <a href=\"https://colin-scott.github.io/personal_website/research/interactive_latency.html\" target=\"_blank\" rel=\"noopener noreferrer\">interactive version</a> adds a year slider, covered in <a href=\"/learn/numbers-to-know#how-these-numbers-have-changed\">How these numbers have changed</a> below.</p>\n<h4 id=\"what-the-table-tells-you\">What the table tells you</h4>\n<p>The exact values matter less than the gaps between them. Here is what the gaps say, in plain sentences.</p>\n<ul>\n<li><strong>Memory is far faster than any disk.</strong> A main memory reference takes 100 ns. A random 4 KB read from an SSD takes 150 µs, which is 1,500 times longer. This is the whole case for caching: keep hot data in memory.</li>\n<li><strong>Sequential reads beat random reads.</strong> A hard disk spends 10 ms just finding the data, and then reads a whole megabyte in 20 ms. If you read 1 MB as 256 separate 4 KB pieces scattered over the disk, you pay 256 seeks, which is about 2.5 seconds. Databases and logs are built around this: they append to the end of a file and read in large blocks.</li>\n<li><strong>The network inside a data center is faster than a local hard disk.</strong> A round trip to another machine in the same building takes 0.5 ms. One disk seek takes 10 ms. So asking another server's memory, for example a cache like memcached or Redis, is quicker than reading your own disk.</li>\n<li><strong>Long-distance round trips are expensive.</strong> California to the Netherlands and back takes 150 ms, which is 300 round trips inside a data center. A page that needs four round trips to a faraway server spends 600 ms waiting before any other work. That is why <a href=\"/learn/dns-and-cdn\">CDNs</a> put content near users, and why APIs used over long distances should avoid many small back-and-forth calls.</li>\n<li><strong>Compression is cheap compared with sending data.</strong> Compressing 1 KB takes 3 µs, and sending 1 KB over a 1 Gbps link takes 10 µs. If compression halves the size, it often pays for itself.</li>\n<li><strong>CPU-level costs are tiny next to I/O.</strong> A branch mispredict or a cache miss matters inside tight loops. In a request that does one disk read or one network call, they disappear.</li>\n</ul>\n<h4 id=\"a-human-scale-version\">A human-scale version</h4>\n<p>Nanoseconds are hard to picture. One way to feel the gaps is to stretch time so that an L1 cache reference takes one second. That multiplies every number by 2 billion.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Operation</th><th>Real time</th><th>If an L1 cache reference took 1 second</th></tr></thead><tbody><tr><td>L1 cache reference</td><td>0.5 ns</td><td>1 second</td></tr><tr><td>Branch mispredict</td><td>5 ns</td><td>10 seconds</td></tr><tr><td>L2 cache reference</td><td>7 ns</td><td>14 seconds</td></tr><tr><td>Mutex lock/unlock</td><td>25 ns</td><td>50 seconds</td></tr><tr><td>Main memory reference</td><td>100 ns</td><td>3.3 minutes</td></tr><tr><td>Compress 1 KB with Zippy</td><td>3 µs</td><td>1.7 hours</td></tr><tr><td>Send 1 KB over a 1 Gbps network</td><td>10 µs</td><td>5.6 hours</td></tr><tr><td>Read 4 KB randomly from SSD</td><td>150 µs</td><td>3.5 days</td></tr><tr><td>Read 1 MB sequentially from memory</td><td>250 µs</td><td>5.8 days</td></tr><tr><td>Round trip within the same data center</td><td>500 µs</td><td>11.6 days</td></tr><tr><td>Read 1 MB sequentially from SSD</td><td>1 ms</td><td>23 days</td></tr><tr><td>HDD seek</td><td>10 ms</td><td>7.6 months</td></tr><tr><td>Read 1 MB sequentially over a 1 Gbps network</td><td>10 ms</td><td>7.6 months</td></tr><tr><td>Read 1 MB sequentially from HDD</td><td>20 ms</td><td>15 months</td></tr><tr><td>California → Netherlands → California</td><td>150 ms</td><td>9.5 years</td></tr></tbody></table></div>\n<p>On this scale, fetching something from memory is a short coffee break. A round trip inside the data center is a two-week holiday. A round trip across the Atlantic takes most of a decade.</p>\n<h4 id=\"handy-metrics-derived-from-the-table\">Handy metrics derived from the table</h4>\n<p>Each rate below comes from one row of the table. Divide the size by the time.</p>\n<ul>\n<li><strong>Hard disk, sequential:</strong> 1 MB in 20 ms, so about <strong>50 MB/s</strong>. (The older Stanford slide's 30 ms per MB gives 30 MB/s, which is the figure Dean used in his own worked examples.)</li>\n<li><strong>1 Gbps Ethernet, sequential:</strong> 1 MB in 10 ms, so about <strong>100 MB/s</strong>. The exact line rate is 125 MB/s; some of it goes to protocol overhead.</li>\n<li><strong>SSD, sequential:</strong> 1 MB in 1 ms, so about <strong>1 GB/s</strong>.</li>\n<li><strong>Main memory, sequential:</strong> 1 MB in 250 µs, so about <strong>4 GB/s</strong>.</li>\n<li><strong>Round trips across the world:</strong> 1 second ÷ 150 ms ≈ <strong>6 to 7 round trips a second</strong>, one after another.</li>\n<li><strong>Round trips within a data center:</strong> 1 second ÷ 0.5 ms = <strong>2,000 round trips a second</strong>, one after another.</li>\n</ul>\n<p>The last two describe one caller waiting for each reply before sending the next request. A server talking to many callers at once can do far more round trips in total.</p>\n<h4 id=\"how-these-numbers-have-changed\">How these numbers have changed</h4>\n<p>Hardware has moved on since the table was written, but unevenly. Colin Scott's <a href=\"https://colin-scott.github.io/personal_website/research/interactive_latency.html\" target=\"_blank\" rel=\"noopener noreferrer\">interactive latency page</a> shows this by letting you pick a year. It starts from Norvig's numbers and applies a trend to each row (<a href=\"https://github.com/colin-scott/interactive_latencies\" target=\"_blank\" rel=\"noopener noreferrer\">source code on GitHub</a>). In its model, CPU clock speed stops rising in 2005, main memory latency stays at 100 ns from 2000 on, the data-center round trip stays at 500 µs, and the California–Netherlands round trip stays at 150 ms because it is limited by the speed of light. Storage and network bandwidth keep growing. Treat the page as a model of trends. Its numbers are extrapolations from older data.</p>\n<p>For a few rows that have moved the most, here is a modern ballpark from current vendor specifications and published measurements. The classic table above stays as it is; use these when you want a number closer to today's hardware.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Row</th><th>Classic table</th><th>A modern ballpark</th><th>Source and year</th></tr></thead><tbody><tr><td>Read 4 KB randomly from SSD</td><td>150 µs</td><td>about 60 µs typical read latency for a data-center NVMe SSD</td><td>Solidigm D7-PS1010 spec table, in <a href=\"https://www.storagereview.com/review/solidigm-ps1010-ssd-review\">StorageReview's review</a>, 2024</td></tr><tr><td>Read 1 MB sequentially from SSD</td><td>1 ms (about 1 GB/s)</td><td>about 70 µs, at up to 14,500 MB/s</td><td><a href=\"https://www.solidigm.com/products/data-center/d7/ps1010.html\">Solidigm D7-PS1010 product page</a>, a PCIe 5.0 drive from 2024</td></tr><tr><td>Round trip within the same data center</td><td>500 µs</td><td>about 50 to 150 µs between two VMs in one cloud zone (netperf mean 67 µs; ping average 146 µs)</td><td>Google Cloud blog, <a href=\"https://cloud.google.com/blog/products/networking/using-netperf-and-ping-to-measure-network-latency\">What a trip! Measuring network latency in the cloud</a>, 2020</td></tr><tr><td>Read 1 MB sequentially from memory</td><td>250 µs (about 4 GB/s)</td><td>a 5th Gen AMD EPYC server CPU has a peak memory bandwidth of 614 GB/s per socket, shared by all its cores</td><td><a href=\"https://www.amd.com/en/products/processors/server/epyc/9005-series/amd-epyc-9575f.html\">AMD EPYC 9575F spec page</a></td></tr><tr><td>HDD seek, and 1 MB from HDD</td><td>10 ms and 20 ms</td><td>average rotational latency 4.16 ms; up to 285 MB/s sustained, so 1 MB in about 3.5 ms; about 170 random 4 KB reads a second</td><td>Seagate Exos data sheet (ds2046.1), current in 2026</td></tr><tr><td>Main memory reference</td><td>100 ns</td><td>still about 100 ns</td><td>Colin Scott's model holds it flat</td></tr><tr><td>California → Netherlands → California</td><td>150 ms</td><td>still about 150 ms</td><td>limited by distance</td></tr></tbody></table></div>\n<p>Some notes on reading this table:</p>\n<ul>\n<li><strong>SSDs improved the most.</strong> Random reads are about 2 to 3 times faster, and sequential reads about 14 times faster. The 14,500 MB/s figure is a peak for large sequential reads. A data-center SSD also handles millions of small reads a second when many run in parallel; the D7-PS1010 page lists up to 3.3 million random 4 KB reads a second.</li>\n<li><strong>Spinning disks got faster at streaming, but not at seeking.</strong> The Seagate figure of 285 MB/s is for the outer edge of the platter, where a disk is fastest. Its 4.16 ms is the average wait for the platter to spin to the right place (half a turn at 7,200 RPM), before counting the head's move. About 170 random reads a second means each one still costs several milliseconds. A disk is still a poor place for random lookups.</li>\n<li><strong>Data-center networks got several times faster.</strong> The Google measurement is between two virtual machines in one zone, using the internal network. Your numbers depend on the cloud, the instance type and the load.</li>\n<li><strong>Memory latency barely moved, but bandwidth grew a lot.</strong> The 614 GB/s figure is a peak for the whole socket, with all 12 memory channels in use. One thread reading on its own gets only part of it.</li>\n<li><strong>The speed of light did not change.</strong> Cross-continent latency is the same as in 2012, which makes it relatively more expensive than everything else that got faster.</li>\n</ul>","headings":[{"id":"latency-numbers-every-programmer-should-know","title":"Latency numbers every programmer should know","depth":3},{"id":"what-the-table-tells-you","title":"What the table tells you","depth":4},{"id":"a-human-scale-version","title":"A human-scale version","depth":4},{"id":"handy-metrics-derived-from-the-table","title":"Handy metrics derived from the table","depth":4},{"id":"how-these-numbers-have-changed","title":"How these numbers have changed","depth":4}]},{"id":"throughput-numbers","title":"Throughput numbers","html":"<h3 id=\"throughput-numbers\">Throughput numbers</h3>\n<p><strong>Throughput</strong> is how much work a system finishes per unit of time: bytes per second for a disk, requests per second for a server. The latency table hides throughput inside its rows. This section pulls it out.</p>\n<h4 id=\"sequential-read-and-transfer-rates\">Sequential read and transfer rates</h4>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Medium</th><th>Rough rate</th><th>Time to move 1 GB</th><th>Where the number comes from</th></tr></thead><tbody><tr><td>Main memory</td><td>4 GB/s in the classic table; up to 614 GB/s peak for a whole modern server socket</td><td>0.25 s classic</td><td>Classic table; AMD EPYC spec page</td></tr><tr><td>NVMe SSD</td><td>1 GB/s classic; up to 14.5 GB/s for a 2024 PCIe 5.0 data-center drive</td><td>1 s classic; about 0.07 s modern</td><td>Classic table; Solidigm D7-PS1010</td></tr><tr><td>Hard disk</td><td>50 MB/s classic; up to 285 MB/s for a current large drive</td><td>20 s classic; about 3.5 s modern</td><td>Classic table; Seagate Exos data sheet</td></tr><tr><td>1 Gbps network</td><td>125 MB/s line rate; plan on about 100 MB/s</td><td>about 10 s</td><td>arithmetic: 1 Gbps ÷ 8 bits per byte</td></tr><tr><td>10 Gbps network</td><td>1.25 GB/s</td><td>about 1 s</td><td>arithmetic</td></tr><tr><td>100 Gbps network</td><td>12.5 GB/s</td><td>about 0.1 s</td><td>arithmetic</td></tr></tbody></table></div>\n<p>A rule of thumb follows from this table. A fast modern SSD reads data about as fast as a 100 Gbps network can carry it, and a hard disk reads about as fast as a 2 Gbps link. So in a data pipeline, the network card often runs out of capacity before the drive does.</p>\n<h4 id=\"requests-per-second-for-one-machine\">Requests per second for one machine</h4>\n<p>How many requests one machine can handle depends heavily on what each request does. The numbers below are rough orders of magnitude for sizing. Real systems often do much less, so measure your own before you commit to a design.</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>Server type</th><th>Rough throughput</th><th>Basis</th></tr></thead><tbody><tr><td>In-memory cache node (Redis)</td><td>about 70,000 to 180,000 simple commands a second without pipelining; over 1.5 million with 16 commands per pipeline</td><td>Examples in the <a href=\"https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/benchmarks/\">Redis benchmark docs</a>. Redis runs commands on mostly one thread, so one instance uses about one core.</td></tr><tr><td>Relational database node, simple reads</td><td>about 530,000 to 840,000 primary-key lookups a second in a synthetic test</td><td>PostgreSQL's <code>pgbench -S</code> (select-only) on a 16-core, 32-thread desktop CPU, with the client on the same machine and all data in memory, <a href=\"https://www.postgresql.org/message-id/CAAKRu_b1hteaenKZ19%3DhUc1vOtixdjT0TfUTnPci22oxoU1MTQ%40mail.gmail.com\">reported on the pgsql-hackers list</a> in 2023</td></tr><tr><td>Relational database node, real workload</td><td><strong>assumption:</strong> about 1,000 to 10,000s of queries a second</td><td>Real queries join tables, write to disk and wait on the network and on locks. This range is a planning assumption.</td></tr><tr><td>Web or app server, dynamic pages</td><td><strong>assumption:</strong> hundreds to a few thousand requests a second</td><td>See the derivation below.</td></tr></tbody></table></div>\n<p>The app server row is easiest to reason about from first principles. If each request needs about 10 ms of CPU time and the server has 16 cores, the most it can do is 16 × (1,000 ms ÷ 10 ms) = 1,600 requests a second. In practice you plan to run well below that peak, because waiting times rise sharply as a server gets close to fully busy (see <a href=\"/learn/performance-and-latency#queueing-why-busy-servers-get-slow-suddenly\">Performance and latency</a>). A server that mostly waits on other services, rather than computing, can hold many more requests at once, and then memory or connection limits set the ceiling instead.</p>\n<p>The gap between the synthetic database result and a real workload is the main lesson of this table. Benchmarks measure the best case. A design should assume much less, and check against measurements once the system exists.</p>","headings":[{"id":"throughput-numbers","title":"Throughput numbers","depth":3},{"id":"sequential-read-and-transfer-rates","title":"Sequential read and transfer rates","depth":4},{"id":"requests-per-second-for-one-machine","title":"Requests per second for one machine","depth":4}]},{"id":"numbers-for-ai-systems","title":"Numbers for AI systems","html":"<h3 id=\"numbers-for-ai-systems\">Numbers for AI systems</h3>\n<p>AI models add a new kind of estimate: will the model fit in memory, and how fast can it run? The basic numbers come from the GPU's specification and from the model's size.</p>\n<p><strong>Memory and bandwidth of one data-center GPU.</strong> NVIDIA's spec pages list:</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<div class=\"table-wrap\"><table><thead><tr><th>GPU</th><th>Memory (HBM)</th><th>Memory bandwidth</th><th>Source</th></tr></thead><tbody><tr><td>H100 SXM</td><td>80 GB</td><td>3.35 TB/s</td><td><a href=\"https://www.nvidia.com/en-us/data-center/h100/\">NVIDIA H100</a></td></tr><tr><td>H100 NVL</td><td>94 GB</td><td>3.9 TB/s</td><td>same page</td></tr><tr><td>H200 SXM</td><td>141 GB</td><td>4.8 TB/s</td><td><a href=\"https://www.nvidia.com/en-us/data-center/h200/\">NVIDIA H200</a></td></tr></tbody></table></div>\n<p>HBM (high-bandwidth memory) is the memory stacked next to the GPU chip. Its bandwidth is several times higher than a whole server CPU socket's memory bandwidth (614 GB/s above).</p>\n<p><strong>How big a model's weights are.</strong> A model's weights take up roughly:</p>\n<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span>weight size = number of parameters × bytes per parameter</span></span></code></pre>\n<p>The bytes per parameter depend on the number format. FP16 and BF16 (16-bit floating point) use 2 bytes. 8-bit formats use 1 byte. 4-bit formats use half a byte. So:</p>\n<ul>\n<li>A 70-billion-parameter model in FP16 takes 70 × 10^9 × 2 bytes = 140 GB.</li>\n<li>The same model in an 8-bit format takes about 70 GB, and in a 4-bit format about 35 GB.</li>\n</ul>\n<p>This is only the weights. Running a model also needs memory for intermediate results, mainly the cache of each conversation's past tokens. So a 140 GB model does not fit on one 80 GB H100, and it only just fits within one H200's 141 GB with almost no room left over. In practice, it would run on two or more GPUs.</p>\n<p><strong>A rough speed limit.</strong> When a model generates text one token at a time for a single user, each new token needs the GPU to read all the weights from memory once. Reading 140 GB at 4.8 TB/s takes about 29 ms. So one H200 can produce at most about 34 tokens a second for that single conversation, however fast its arithmetic units are. Serving many users at once in the same pass over the weights is how real systems get much higher total throughput.</p>\n<p>The gist that popularized the latency table added rows for language models in 2026. They are rough, but useful for scale: a hosted frontier model produces a token about every 20 ms, takes about 1 second before its first token on a short prompt, about 10 seconds to read a 100,000-token prompt with no cache, and about 30 seconds for a single reasoning response.</p>\n<p>A later part of the handbook covers model inference in depth: batching, caching, and how to size a serving fleet.</p>","headings":[{"id":"numbers-for-ai-systems","title":"Numbers for AI systems","depth":3}]},{"id":"check-yourself","title":"Check yourself","html":"<h3 id=\"check-yourself\">Check yourself</h3>\n<details>\n<summary>How long does it take to read a 1 GB file from memory, from an SSD, from a hard disk, and over a 1 Gbps network, using the classic table?</summary>\n<p>Work from the 1 MB rows and multiply by 1,000.</p>\n<ul>\n<li>Memory: 1,000 × 250 µs = 0.25 seconds.</li>\n<li>SSD: 1,000 × 1 ms = 1 second.</li>\n<li>Hard disk: 1,000 × 20 ms = 20 seconds.</li>\n<li>1 Gbps network: 1,000 × 10 ms = 10 seconds (8 seconds at the exact line rate).</li>\n</ul>\n<p>With a 2024 PCIe 5.0 SSD at 14.5 GB/s, the SSD read drops to about 0.07 seconds, faster than the classic table's memory figure.</p>\n</details>\n<details>\n<summary>A page shows 100 thumbnails of 256 KB each, stored on hard disks. Estimate the time if you read them one after another, and if you read them all in parallel from many disks.</summary>\n<p>Each read needs one seek (10 ms) plus 0.256 MB at 20 ms per MB (about 5 ms). That is about 15 ms per thumbnail.</p>\n<ul>\n<li>One after another: 100 × 15 ms = 1.5 seconds.</li>\n<li>In parallel, with each image on a different disk: about 15 ms, plus some extra for the slowest disk.</li>\n</ul>\n<p>If the thumbnails sit in a memory cache instead, reading all 25.6 MB takes about 25.6 × 250 µs ≈ 6.4 ms. Jeff Dean's 2009 slides used the same kind of estimate for a page of 30 thumbnails: about 560 ms read one at a time, about 18 ms read in parallel.</p>\n</details>\n<details>\n<summary>Your service will hand out IDs to about 6 billion objects. Is a 32-bit integer enough?</summary>\n<p>No. 2^32 = 4,294,967,296, about 4.3 billion, which is fewer than 6 billion. A signed 32-bit integer only reaches about 2.1 billion. Use a 64-bit ID, which holds about 1.8 × 10^19 values. See <a href=\"/learn/unique-ids\">Unique IDs</a> for ways to generate them.</p>\n</details>\n<details>\n<summary>You need to copy a 10 TB backup between two data centers. How long does it take over a 1 Gbps link, and over a 10 Gbps link?</summary>\n<p>10 TB = 10 × 10^12 bytes × 8 = 8 × 10^13 bits.</p>\n<ul>\n<li>At 1 Gbps: 8 × 10^13 ÷ 10^9 = 80,000 seconds, about 22 hours.</li>\n<li>At 10 Gbps: 8,000 seconds, about 2.2 hours.</li>\n</ul>\n<p>Both assume the link runs at full speed the whole time, which real transfers rarely do. Add some margin.</p>\n</details>\n<details>\n<summary>A user in Europe loads a page from a server in California. The page needs 4 sequential round trips before it can show anything. What is the minimum wait, and what would you change?</summary>\n<p>Each round trip takes about 150 ms, so 4 × 150 ms = 600 ms before any server work. Faster servers can't fix this, because the time goes on distance. Serve the content from a location near the user with a <a href=\"/learn/dns-and-cdn\">CDN</a> or a nearby data center, and cut the number of round trips, for example by reusing connections and combining requests.</p>\n</details>\n<details>\n<summary>Can a 70-billion-parameter model in FP16 run on a single 80 GB H100? What about in an 8-bit format?</summary>\n<p>In FP16 the weights alone take 70 × 10^9 × 2 bytes = 140 GB, which is far more than 80 GB, so it needs at least two GPUs. In an 8-bit format the weights take about 70 GB. That fits, but it leaves only about 10 GB for the per-conversation cache and other working memory, which limits how many users it can serve at once.</p>\n</details>\n<h3 id=\"further-reading\">Further reading</h3>\n<p>The classic sources for the latency table:</p>\n<ul>\n<li><a href=\"https://gist.github.com/jboner/2841832\" target=\"_blank\" rel=\"noopener noreferrer\">Latency numbers every programmer should know</a>: Jonas Bonér's gist, the version most people copy, with credits and later additions.</li>\n<li><a href=\"https://gist.github.com/hellerbarde/2843375\" target=\"_blank\" rel=\"noopener noreferrer\">\"Humanized\" latency numbers</a>: a second gist with a human-scale version of the table.</li>\n<li><a href=\"https://i.imgur.com/k0t1e.png\" target=\"_blank\" rel=\"noopener noreferrer\">Visual chart of the latency numbers</a>: the table drawn as grids of squares.</li>\n<li><a href=\"https://norvig.com/21-days.html#answers\" target=\"_blank\" rel=\"noopener noreferrer\">Teach Yourself Programming in Ten Years</a>: Peter Norvig's essay; the timing table is in its answers section.</li>\n<li><a href=\"https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">Designs, Lessons and Advice from Building Large Distributed Systems</a>: Jeff Dean's LADIS 2009 keynote. \"Numbers Everyone Should Know\" and the thumbnail estimate are on slides 24 to 27.</li>\n<li><a href=\"https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">Software Engineering Advice from Building Large-Scale Distributed Systems</a>: Jeff Dean's earlier Stanford talk, with the older version of the table.</li>\n<li><a href=\"https://colin-scott.github.io/personal_website/research/interactive_latency.html\" target=\"_blank\" rel=\"noopener noreferrer\">Latency Numbers Every Programmer Should Know (interactive)</a>: Colin Scott's page with a year slider.</li>\n</ul>\n<p>Units and modern figures:</p>\n<ul>\n<li><a href=\"https://en.wikipedia.org/wiki/Power_of_two\" target=\"_blank\" rel=\"noopener noreferrer\">Power of two</a>: Wikipedia's article, with a longer table of powers.</li>\n<li><a href=\"https://physics.nist.gov/cuu/Units/binary.html\" target=\"_blank\" rel=\"noopener noreferrer\">Prefixes for binary multiples</a>: NIST on KiB, MiB and GiB.</li>\n<li><a href=\"https://cloud.google.com/blog/products/networking/using-netperf-and-ping-to-measure-network-latency\" target=\"_blank\" rel=\"noopener noreferrer\">What a trip! Measuring network latency in the cloud</a>: how to measure round-trip time between machines, and why the settings change the result.</li>\n<li><a href=\"https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/benchmarks/\" target=\"_blank\" rel=\"noopener noreferrer\">Redis benchmark</a>: how to benchmark a cache node, and the pitfalls that make benchmarks misleading.</li>\n<li><a href=\"/learn/estimation\">Back-of-the-envelope estimation</a>: the step-by-step method that uses these numbers.</li>\n</ul>","headings":[{"id":"check-yourself","title":"Check yourself","depth":3},{"id":"further-reading","title":"Further reading","depth":3}]}]}