block by mbostock 5503544

Gist API Latency

Full Screen

This histogram shows the distribution of GitHub Gist API response times (in milliseconds) for a sample of 10,000 requests as observed by bl.ocks.org.

The distribution roughly follows a log-normal distribution, which is unsurprising for a complex process that has multiple independently-random sources of delay. The mode response time was in the range 120-140ms, while the median response time was 206ms. The middle 80% of requests were in the range 114-527ms. About 11% of requests took longer than 500ms, and 5% of requests took longer than one second. (The rightmost bin in the histogram includes these long requests.)

Since API endpoints vary dramatically in their computational cost, the distribution of response times is likely multimodal. In this dataset, 96% of requests were for a single gist (/gists/42), while the remaining 4% of requests were to list a user’s gist (/users/fred/gists). By separating the API requests for a single gist (shown in light blue) from listing a user’s gists (shown in dark blue), we see that the cause for the slow requests is not random but a function of the endpoint! The response time distribution to list a user’s gists is significantly slower than querying a single gist.

This data was collected by from the bl.ocks.org Heroku app via cube-logplex and queried via Cube.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.bar rect {
  fill: #1f77b4;
  shape-rendering: crispEdges;
}

.bar .a {
  fill: #aec7e8;
}

.bar text {
  text-anchor: end;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var formatPercent = d3.format(".1%");

var margin = {top: 10, right: 30, bottom: 30, left: 30},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .domain([0, 1000])
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

d3.tsv("histogram.tsv", type, function(error, histogram) {
  var n = d3.sum(histogram, function(d) { return d.y = d.a + d.b; });

  y.domain([0, d3.max(histogram, function(d) { return d.y; })]);

  var bar = svg.insert("g", ".axis")
      .attr("class", "bar")
    .selectAll("g")
      .data(histogram)
    .enter().append("g")
      .attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });

  bar.append("rect")
      .attr("class", "b")
      .attr("x", 1)
      .attr("y", function(d) { return y(d.b); })
      .attr("width", x(histogram[0].dx) - 1)
      .attr("height", function(d) { return height - y(d.b); });

  bar.append("rect")
      .attr("class", "a")
      .attr("x", 1)
      .attr("y", function(d) { return y(d.y); })
      .attr("width", x(histogram[0].dx) - 1)
      .attr("height", function(d) { return height - y(d.a); });

  bar.filter(function(d) { return d.y / n >= .0095; }).append("text")
      .attr("dy", ".35em")
      .attr("transform", function(d) { return "translate(" + x(histogram[0].dx) / 2 + "," + (y(d.y) + 6) + ")rotate(-90)"; })
      .text(function(d) { return formatPercent(d.y / n); });
});

function type(d) {
  d.x = +d.x;
  d.dx = +d.dx;
  d.a = +d.a;
  d.b = +d.b;
  return d;
}

</script>

histogram.tsv

x	dx	a	b
0	20	0	0
20	20	0	3
40	20	2	15
60	20	121	2
80	20	306	2
100	20	811	0
120	20	1022	3
140	20	910	5
160	20	799	1
180	20	709	1
200	20	593	1
220	20	600	0
240	20	501	1
260	20	408	1
280	20	358	0
300	20	316	0
320	20	256	0
340	20	252	2
360	20	200	1
380	20	161	0
400	20	121	3
420	20	103	2
440	20	107	1
460	20	74	0
480	20	73	1
500	20	61	0
520	20	63	0
540	20	56	0
560	20	44	1
580	20	28	0
600	20	30	0
620	20	27	0
640	20	30	1
660	20	24	1
680	20	15	1
700	20	15	1
720	20	24	1
740	20	18	1
760	20	17	2
780	20	14	0
800	20	19	1
820	20	21	1
840	20	7	0
860	20	11	4
880	20	11	1
900	20	7	2
920	20	15	3
940	20	14	3
960	20	8	3
980	20	256	290