<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var year = new Date().getFullYear();
function shift(year) {
return year - 1982;
}
function getPayloadBytes() {
return Math.pow(10, 6);
}
function getNetworkPayloadBytes() {
return 2 * Math.pow(10,3);
}
function getCycle() {
if (year <= 2005) {
var a = 3 * Math.pow(10, 9) / Math.pow(2,shift(2005) * 0.5);
var b = Math.pow(2, 1.0/2);
var hz = a * Math.pow(b, shift(year));
} else {
var hz = 3 * Math.pow(10,9);
}
var ns = Math.pow(10,9) / hz;
return ns;
}
function getMemLatency() {
if (year <= 2000) {
var b = 0.93;
var a = 100.0 / Math.pow(0.93,shift(2000));
var ms = a * Math.pow(b, shift(year));
} else {
var ms = 100;
}
return ms;
}
function getNICTransmissionDelay(payloadBytes) {
var a = 125 * Math.pow(10,6) / Math.pow(2,shift(2003) * 0.5);
var b = Math.pow(2, 1.0/2);
var bw = a * Math.pow(b, shift(year));
var ns = payloadBytes / (bw / Math.pow(10,9));
return ns;
}
function getBusTransmissionDelay(payloadBytes) {
var a = 4*Math.pow(10, 9) / Math.pow(2,shift(2001) * 0.33);
var b = Math.pow(2,1.0/3);
var bw = a * Math.pow(b, shift(year));
var ns = payloadBytes / (bw / Math.pow(10,9));
return ns;
}
function getSSDLatency() {
if (year <= 2014) {
var a = 2 * Math.pow(10,4) / Math.pow(1.0/20, shift(year) * 0.22);
var b = Math.pow(1.0/20, 1.0/4.5);
return a * Math.pow(b,shift(year));
} else {
return 16000;
}
}
function getSSDTransmissionDelay(payloadBytes) {
var a = 3*Math.pow(10, 9) / Math.pow(2,shift(2012) * 0.33);
var b = Math.pow(2, 1.0/3);
var bw = a*Math.pow(b, shift(year));
var ns = payloadBytes / (bw / Math.pow(10,9));
return ns;
}
function getSeek() {
var a = Math.pow(10,7) / Math.pow(0.5,shift(2000)*0.1);
var b = Math.pow(0.5,0.1);
var ns = a * Math.pow(b, shift(year));
return ns;
}
function getDiskTransmissionDelay(payloadBytes) {
if (year <= 2002) {
var a = Math.pow(10,8) / Math.pow(2,shift(2002) * 0.5);
var b = Math.pow(2,1.0/2);
var bw = a * Math.pow(b, shift(year));
} else {
var a = Math.pow(10,8) / Math.pow(2,shift(2002) * 0.2);
var b = Math.pow(2,1.0/5);
var bw = a * Math.pow(b, shift(year));
}
var ns = payloadBytes / (bw / Math.pow(10,9));
return ns;
}
function getDCRTT() {
return 500000;
}
function getWanRTT() {
return 150000000;
}
function drawBoxes(n, div, color) {
var cw = 100;
var ch = (n / 10) * 10;
if ((n % 10) != 0) {
ch += 10;
}
var rects = d3.select("#" + div).
append("svg:svg").
attr("width", cw).
attr("height", ch);
var length = 10;
var whitespace = 2;
for (var y = 0; y < ch; y+=length) {
for (var x = 0; x < cw; x+=length) {
if (n > 0 && n < 1) {
var width = n * length;
} else {
var width = length;
}
rects.append("svg:rect").
attr("x", x).
attr("y", y).
attr("height", length).
attr("width", width).
attr("style", color);
n -= 1;
if (n <= 0) {
return;
}
}
}
}
function singleBox(color) {
s = '<svg width="11" height="11">';
s += '<rect x="0" y="0" height="10" width="10" style="';
s += color + '"></rect>';
s += '</svg>';
return s;
}
var black = "stroke:#FFFFFF; fill: #000000";
var blue = "stroke:#FFFFFF; fill: #0000FF";
var green = "stroke:#FFFFFF; fill: #00CC00";
var red = "stroke:#FFFFFF; fill: #FF0000";
function addCommas(nStr) {
if (nStr < 1) {
nStr = nStr.toFixed(1);
} else {
nStr = nStr.toFixed(0);
}
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
function Metric(ns, boxType, displayString, div, optionalSuffix) {
this.ns = ns;
if (boxType == "ns") {
this.color = black;
this.boxes = ns;
this.nsDisplay = addCommas(ns);
this.alternateUnit = "";
} else if (boxType == "100ns") {
this.color = blue;
this.boxes = ns / 100;
var us = ns / 1000;
if (us >= 1) {
this.nsDisplay = addCommas(Math.round(ns / 1000) * 1000);
this.alternateUnit = " ≈ " + addCommas(ns / 1000) + "μs";
} else {
this.nsDisplay = addCommas(ns);
this.alternateUnit = "";
}
} else if (boxType == "10us") {
this.color = green;
this.boxes = ns / 10000;
if (displayString != "") {
var us = ns / 1000;
if (us >= 1) {
this.nsDisplay = addCommas(Math.round(ns / 1000) * 1000);
this.alternateUnit = " ≈ " + addCommas(ns / 1000) + "μs";
} else {
this.nsDisplay = addCommas(ns);
this.alternateUnit = "";
}
} else {
this.nsDisplay = addCommas(Math.round(ns / 1000) * 1000);
this.alternateUnit = " = 1ms";
}
} else if (boxType == "ms") {
this.color = red;
this.boxes = ns * Math.pow(10, -6);
var ms = ns * Math.pow(10, -6);
if (ms >= 1) {
this.nsDisplay = addCommas(Math.round(ns / 1000000) * 1000000);
this.alternateUnit = " ≈ " + addCommas(ns / 1000000) + "ms";
} else {
var us = ns / 1000;
if (us >= 1) {
this.nsDisplay = addCommas(Math.round(ns / 1000) * 1000);
this.alternateUnit = " ≈ " + addCommas(ns / 1000) + "μs";
} else {
this.nsDisplay = addCommas(ns);
this.alternateUnit = "";
}
}
}
if (typeof optionalSuffix === "undefined") {
optionalSuffix = "";
}
this.displayString = (displayString + this.nsDisplay + "ns" +
this.alternateUnit + " " + optionalSuffix);
this.div = div;
this.fillDiv = function() {
document.getElementById(this.div).innerHTML = "";
drawBoxes(this.boxes, this.div, this.color);
document.getElementById(this.div + "t").innerHTML = this.displayString;
}
}
function getMetrics() {
var ns = new Metric(1, "ns", "", "ns");
var L1 = new Metric(3*getCycle(), "ns", "L1 cache reference: ", "L1");
var branch = new Metric(10*getCycle(), "ns", "Branch mispredict: ", "branch");
var L2 = new Metric(13*getCycle(), "ns", "L2 cache reference: ", "L2");
var mutex = new Metric(50*getCycle(), "ns", "Mutex lock/unlock: ", "mutex");
var ns100 = new Metric(100, "ns", "", "ns100", ' = ' + singleBox(blue));
var mem = new Metric(getMemLatency(), "100ns", "Main memory reference: ", "mem");
var micro = new Metric(100*10, "100ns", "", "micro");
var zippy = new Metric(6000 * getCycle(), "100ns", "Compress 1KB wth Zippy: ",
"zippy");
var tenMicro = new Metric(100*100, "100ns", "", "tenMicro", ' = ' + singleBox(green));
var network = new Metric(getNICTransmissionDelay(getNetworkPayloadBytes()), "10us",
"Send " + addCommas(getNetworkPayloadBytes()) + " bytes over commodity network: ", "network");
var ssdRandom = new Metric(getSSDLatency(), "10us", "SSD random read: ", "ssdRandom");
var mbMem = new Metric(getBusTransmissionDelay(getPayloadBytes()), "10us",
"Read " + addCommas(getPayloadBytes()) + " bytes sequentially from memory: ", "mbMem");
var rtt = new Metric(getDCRTT(), "10us", "Round trip in same datacenter: ", "rtt");
var ms = new Metric(100*100*100, "10us", "", "ms", ' = ' + singleBox(red));
var mbSSD = new Metric(getSSDTransmissionDelay(getPayloadBytes()), "ms",
"Read " + addCommas(getPayloadBytes()) + " bytes sequentially from SSD: ", "mbSSD");
var seek = new Metric(getSeek(), "ms", "Disk seek: ", "seek");
var mbDisk = new Metric(getDiskTransmissionDelay(getPayloadBytes()), "ms",
"Read " + addCommas(getPayloadBytes()) + " bytes sequentially from disk: ", "mbDisk");
var wan = new Metric(getWanRTT(), "ms", "Packet roundtrip CA to Netherlands: ", "wan");
var metrics = new Array(ns,L1,branch,L2,mutex,ns100,mem,micro,zippy,tenMicro,network,
ssdRandom,mbMem,rtt,ms,mbSSD,seek,mbDisk,wan);
return metrics;
}
<!-- Slider: -->
$(function() {
$( "#slider" ).slider({
value: year,
min: 1990,
max: 2020,
step: 1,
slide: function( event, ui ) {
$( "#amount" ).val( ui.value );
year = ui.value;
render();
}
});
$( "#amount" ).val( $( "#slider" ).slider( "value" ) );
});
</script>
<link href="lib/bootstrap.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.sidebar-nav {
padding: 9px 0;
}
</style>
<link href="lib/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<h4> Latency Numbers Every Programmer Should Know</h4>
<div class="row-fluid">
<div class="span7 offset5">
<input type="text" id="amount" style="border: 0; font-weight: bold;" />
</div>
</div>
<div id="slider">
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span3">
<div class="row-fluid">
<div class="span4" id="ns"></div>
<div class="span8" id="nst"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="L1"></div>
<div class="span8" id="L1t"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="branch"></div>
<div class="span8" id="brancht"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="L2"></div>
<div class="span8" id="L2t"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="mutex"></div>
<div class="span8" id="mutext"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="ns100"></div>
<div class="span8" id="ns100t"></div>
</div>
</div>
<div class="span3">
<div class="row-fluid">
<div class="span4" id="mem"></div>
<div class="span8" id="memt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="micro"></div>
<div class="span8" id="microt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="zippy"></div>
<div class="span8" id="zippyt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="tenMicro"></div>
<div class="span8" id="tenMicrot"></div>
</div>
</div>
<div class="span3">
<div class="row-fluid">
<div class="span4" id="network"></div>
<div class="span8" id="networkt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="ssdRandom"></div>
<div class="span8" id="ssdRandomt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="mbMem"></div>
<div class="span8" id="mbMemt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="rtt"></div>
<div class="span8" id="rttt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="ms"></div>
<div class="span8" id="mst"></div>
</div>
</div>
<div class="span3">
<div class="row-fluid">
<div class="span4" id="mbSSD"></div>
<div class="span8" id="mbSSDt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="seek"></div>
<div class="span8" id="seekt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="mbDisk"></div>
<div class="span8" id="mbDiskt"></div>
</div>
<div class="row-fluid">
<div class="span12"></div>
</div>
<div class="row-fluid">
<div class="span4" id="wan"></div>
<div class="span8" id="want"></div>
</div>
</div>
</div>
</div>
<script>
function render() {
var metrics = getMetrics();
for (var i in metrics) {
var metric = metrics[i];
metric.fillDiv();
}
}
render();
</script>
</body>
</html>