Skip to content

Commit

Permalink
Add annotations to timeline graphs for noteworthy events
Browse files Browse the repository at this point in the history
refs #271
  • Loading branch information
rwstauner committed Nov 22, 2024
1 parent d4e97bd commit 0ea71b5
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<!-- This is the smaller four-up timeline report shown on the front page -->

<script src="/assets/js/d3.v5.js"></script>

<% if @series.size != 4 && @series.size != 8
raise "The mini_timeline graph assumes a 2x2 grid of benchmarks - either 4 series or 8 for multiplatform, not #{@series.size.inspect}!"
end %>
Expand Down Expand Up @@ -81,6 +79,8 @@ var realSVG = d3.select("#mini_timeline")
.attr("xmlns", "http://www.w3.org/2000/svg")
.attr("xmlns:xlink", "http://www.w3.org/1999/xlink")

prepareEventAnnotations(realSVG.append("defs"));

// This is the non-blank center area of the graph, inside the margins
var svg = realSVG.append("g")
.attr("transform",
Expand Down Expand Up @@ -201,6 +201,8 @@ subGraphs.forEach(function(subGraph) {
.call(yAxis)
;

addEventAnnotations({svg: subgraph, x, y});

subGraph.series.forEach(function(thisSeries) {
var graphLine = subgraph.append("path")
.datum(thisSeries.data)
Expand Down
5 changes: 5 additions & 0 deletions site/_framework/render.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ def configure_args(args)
arg.match?(%r{^[^-a-zA-Z]|[^[-_a-zA-Z0-9:@\/=]]}) ? "'#{arg}'" : arg
end.compact
end

TIMELINE_EVENTS = YAML.load_file(File.expand_path("../../events.yaml", __dir__))
def timeline_events
TIMELINE_EVENTS
end
end

def read_front_matter(path)
Expand Down
42 changes: 0 additions & 42 deletions site/_includes/events.json

This file was deleted.

6 changes: 6 additions & 0 deletions site/_layouts/basic.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ title: "YJIT Benchmarks"
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<script src="assets/js/clipboard.min.js"></script>
<%# Include the timeline stuff for the mini timelines at the bottom of the index. %>
<script src="<%= asset_url('js/d3.v5.js') %>"></script>
<script type="text/javascript">
window.timeline_events = <%= JSON.generate(timeline_events) %>;
</script>
<script src="<%= asset_url('js/timeline.js') %>"></script>
<link rel="stylesheet" type="text/css" media="screen" href="<%= asset_url('css/style.css') %>">
<title><%= title %></title>

Expand Down
3 changes: 3 additions & 0 deletions site/_layouts/timeline.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ title: "YJIT Benchmarks"
<meta name="viewport" content="width=device-width,maximum-scale=2">
<script src="<%= asset_url('js/clipboard.min.js') %>"></script>
<script src="<%= asset_url('js/d3.v5.js') %>"></script>
<script type="text/javascript">
window.timeline_events = <%= JSON.generate(timeline_events) %>;
</script>
<script src="<%= asset_url('js/timeline.js') %>"></script>
<link rel="stylesheet" type="text/css" media="screen" href="<%= asset_url('css/style.css') %>">
<title><%= title %></title>
Expand Down
72 changes: 71 additions & 1 deletion site/assets/js/timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var all_series_time_range;
var svg;
var checkboxes;
var timeline = {
annotationColor: "#1117",
dashSize: 1.5,
whiskers: false,
whiskerColor: "#1117",
whiskerStrokeWidth: 1.0,
Expand All @@ -13,6 +15,13 @@ var timeline = {

document.timeline_data = {} // For sharing data w/ handlers

document.timeline_data.events = window.timeline_events.map(e => {
return {
time: timeParser(e.time),
desc: e.description,
}
});

function initSVG(opts) {
// D3 line graph, based on https://www.d3-graph-gallery.com/graph/line_basic.html
// set the dimensions and margins of the graph
Expand Down Expand Up @@ -60,14 +69,17 @@ function initSVG(opts) {
.call(document.timeline_data.y_axis);

// Define viewport to clip graphs to.
svg.append("defs").append("svg:clipPath")
var defs = svg.append("defs");
defs.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);

prepareEventAnnotations(defs);

var brush = d3.brushX() // Add the brush feature using the d3.brush function
.extent( [ [0,0], [width,height] ] ) // initialise the brush area: start at 0,0 and finishes at width,height: it means I select the whole graph area
.on("end", updateChart);
Expand All @@ -79,6 +91,40 @@ function initSVG(opts) {
.call(brush);
}

function prepareEventAnnotations(defs) {
// Add a pattern mask that we can use to create the appearance of dashed lines
// without having the mouse move in and out at each dash of the stroke.
var dashed = defs.append("svg:pattern")
.attr("id", "dashed")
.attr("x", 0)
.attr("y", 0)
.attr("width", timeline.dashSize)
.attr("height", timeline.dashSize * 2)
.attr("patternUnits", "userSpaceOnUse")

dashed.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", timeline.dashSize)
.attr("height", timeline.dashSize)
.attr("fill", "#000");
dashed.append("svg:rect")
.attr("x", 0)
.attr("y", timeline.dashSize)
.attr("width", timeline.dashSize)
.attr("height", timeline.dashSize)
.attr("fill", "#fff");

defs.append("svg:mask")
.attr("id", "dash-mask")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "url(#dashed)");
}

function rescaleGraphFromFetchedData() {
updateAllFromCheckboxes();
updateGraphFromData();
Expand Down Expand Up @@ -315,6 +361,28 @@ var updateDomainsAndAxesFromData = buildUpdateDomainsAndAxesFromData(function(se
return series.value_range ||= getMinMax(series.data.map(x => x.value));
});

// Add svg group with timeline event annotations (vertical lines at time of event).
function addEventAnnotations({svg, x, y}) {
var group = svg.select("g.events")
if (!group.node())
group = svg.append("g").attr("class", "events")

// We use a rect with a mask to simulate a dashed line but avoid frustration
// when trying to hover the stroke to see the tooltip.
group.selectAll("rect.event")
.data(document.timeline_data.events, (d) => d.time)
.join("rect")
.attr("class", "event")
.attr("x", function(d) { return x(d.time) } )
.attr("y", y.range()[1])
.attr("width", timeline.dashSize)
.attr("height", y.range()[0])
.attr("data-tooltip", function(d) { return timePrinter(d.time) + ": " + d.desc })
.attr("fill", timeline.annotationColor)
.attr("mask", "url(#dash-mask)")
.attr("clip-path", "url(#clip)")
}

function updateGraphFromData() {
updateDomainsAndAxesFromData();
var x = document.timeline_data.x_axis_function;
Expand All @@ -328,6 +396,8 @@ function updateGraphFromData() {
.attr("visibility", d => d.visible ? "visible" : "hidden")
;

addEventAnnotations({svg, x, y});

data_series.forEach(function(item) {
var group = svg.select("svg g.svg_tl_data." + item.name);

Expand Down
2 changes: 2 additions & 0 deletions site/memory_timeline.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function updateGraphFromData() {
.attr("visibility", d => d.visible ? "visible" : "hidden")
;

addEventAnnotations({svg, x, y});

data_series.forEach(function(item) {
var group = svg.select("svg g.svg_tl_data." + item.name);

Expand Down
2 changes: 2 additions & 0 deletions site/stats-timeline.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ function updateGraphFromData() {
.attr("visibility", d => d.visible ? "visible" : "hidden")
;

addEventAnnotations({svg, x, y});

data_series.forEach(function(item) {
var current_stat = document.timeline_data.current_stat;
var data = item.data.filter(x => x[current_stat] != null);
Expand Down

0 comments on commit 0ea71b5

Please sign in to comment.