From 0ea71b5fcdcb261c354093790cdddcae38a5ed57 Mon Sep 17 00:00:00 2001 From: Randy Stauner Date: Fri, 22 Nov 2024 09:39:09 -0700 Subject: [PATCH] Add annotations to timeline graphs for noteworthy events refs #271 --- .../mini_timeline_d3_template.html.erb | 6 +- site/_framework/render.rb | 5 ++ site/_includes/events.json | 42 ----------- site/_layouts/basic.erb | 6 ++ site/_layouts/timeline.erb | 3 + site/assets/js/timeline.js | 72 ++++++++++++++++++- site/memory_timeline.html.erb | 2 + site/stats-timeline.html.erb | 2 + 8 files changed, 93 insertions(+), 45 deletions(-) delete mode 100644 site/_includes/events.json diff --git a/lib/yjit_metrics/report_templates/mini_timeline_d3_template.html.erb b/lib/yjit_metrics/report_templates/mini_timeline_d3_template.html.erb index 8956ca2a7..d9115a97c 100644 --- a/lib/yjit_metrics/report_templates/mini_timeline_d3_template.html.erb +++ b/lib/yjit_metrics/report_templates/mini_timeline_d3_template.html.erb @@ -1,7 +1,5 @@ - - <% 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 %> @@ -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", @@ -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) diff --git a/site/_framework/render.rb b/site/_framework/render.rb index 1c799a4c0..8cacac2f8 100644 --- a/site/_framework/render.rb +++ b/site/_framework/render.rb @@ -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) diff --git a/site/_includes/events.json b/site/_includes/events.json deleted file mode 100644 index cc0dc9891..000000000 --- a/site/_includes/events.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "time": "2022-01-26 22:00:00", - "description": "Drop in performance due to changing AWS instances" - }, - { - "time": "2022-05-09 19:00:00", - "description": "Slowdown due to CRuby commit 85479b34f76d5b426c2a8" - }, - { - "time": "2022-06-08 19:00:00", - "description": "Fix for May 9th slowdown, commit 8d57336360497e94" - }, - { - "time": "2022-06-07 19:00:00", - "description": "Slowdown in some benchmarks due to configuring local Rubies with CC=clang" - }, - { - "time": "2022-06-09 19:00:00", - "description": "Revert CC=clang config in yjit-metrics, fix June 7th slowdown" - }, - { - "time": "2022-09-30 06:00:00", - "description": "ARM64 and yjit-metrics multiplatform changes; changes to warmup params; general benchmarking churn" - }, - { - "time": "2023-01-10 08:00:00", - "description": "Several ActiveRecord benchmark changes in functionality, which resulted in lower speed" - }, - { - "time": "2023-01-20 08:00:00", - "description": "Switchover to Jenkins, plus changes in warmup behaviour, though on same ARM AWS worker and different x86 AWS worker." - }, - { - "time": "2023-03-01 12:22:00", - "description": "Added srand to yjit-metrics test harness" - }, - { - "time": "2023-03-02 14:50:00", - "description": "Changed peak_mem_bytes to use /proc/smaps_rollup on Linux, not ps" - } -] diff --git a/site/_layouts/basic.erb b/site/_layouts/basic.erb index fcdfaa042..40109d7e3 100644 --- a/site/_layouts/basic.erb +++ b/site/_layouts/basic.erb @@ -10,6 +10,12 @@ title: "YJIT Benchmarks" + <%# Include the timeline stuff for the mini timelines at the bottom of the index. %> + + + <%= title %> diff --git a/site/_layouts/timeline.erb b/site/_layouts/timeline.erb index 707005552..c0befced7 100644 --- a/site/_layouts/timeline.erb +++ b/site/_layouts/timeline.erb @@ -10,6 +10,9 @@ title: "YJIT Benchmarks" + <%= title %> diff --git a/site/assets/js/timeline.js b/site/assets/js/timeline.js index c9a113784..cec262c71 100644 --- a/site/assets/js/timeline.js +++ b/site/assets/js/timeline.js @@ -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, @@ -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 @@ -60,7 +69,8 @@ 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) @@ -68,6 +78,8 @@ function initSVG(opts) { .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); @@ -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(); @@ -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; @@ -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); diff --git a/site/memory_timeline.html.erb b/site/memory_timeline.html.erb index f2780ef91..3958f5240 100644 --- a/site/memory_timeline.html.erb +++ b/site/memory_timeline.html.erb @@ -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); diff --git a/site/stats-timeline.html.erb b/site/stats-timeline.html.erb index 6499a31c9..04d78b88d 100644 --- a/site/stats-timeline.html.erb +++ b/site/stats-timeline.html.erb @@ -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);