Skip to content

Commit f92b547

Browse files
committed
Render up to 15 days of future in the benchmark detail graph
1 parent 2fd03b9 commit f92b547

File tree

4 files changed

+133
-15
lines changed

4 files changed

+133
-15
lines changed

site/frontend/src/graph/render.ts

+5
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ function genPlotOpts({
158158
alpha = 0.3,
159159
prox = 5,
160160
absoluteMode,
161+
hooks,
161162
}) {
162163
return {
163164
width,
@@ -237,6 +238,7 @@ function genPlotOpts({
237238
ctx.stroke();
238239
},
239240
],
241+
...hooks,
240242
},
241243
},
242244
tooltipPlugin({
@@ -280,6 +282,7 @@ function normalizeData(data: GraphData) {
280282

281283
export type GraphRenderOpts = {
282284
renderTitle?: boolean;
285+
hooks?: {drawSeries: (uPlot, number) => void};
283286
};
284287

285288
// Renders the plots data with the given parameters from the `selector` into
@@ -291,6 +294,7 @@ export function renderPlots(
291294
opts?: GraphRenderOpts
292295
) {
293296
const renderTitle = opts?.renderTitle ?? true;
297+
const hooks = opts?.hooks ?? {};
294298

295299
normalizeData(data);
296300

@@ -379,6 +383,7 @@ export function renderPlots(
379383
return indices.has(dataIdx);
380384
},
381385
absoluteMode: selector.kind == "raw",
386+
hooks,
382387
});
383388
if (renderTitle) {
384389
plotOpts["title"] = `${benchName}-${benchKind}`;

site/frontend/src/pages/compare/compile/table/benchmark-detail.vue

+102-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import {
88
import {computed, onMounted, Ref, ref} from "vue";
99
import Tooltip from "../../tooltip.vue";
1010
import {ArtifactDescription} from "../../types";
11-
import {getDateInPast} from "./utils";
12-
import {renderPlots} from "../../../../graph/render";
11+
import {daysBetweenDates, getFutureDate, getPastDate} from "./utils";
12+
import {GraphRenderOpts, renderPlots} from "../../../../graph/render";
1313
import {GRAPH_RESOLVER} from "../../../../graph/resolver";
1414
import {GraphKind} from "../../../../graph/data";
15+
import uPlot from "uplot";
1516
1617
const props = defineProps<{
1718
testCase: CompileTestCase;
@@ -20,23 +21,116 @@ const props = defineProps<{
2021
benchmarkMap: CompileBenchmarkMap;
2122
}>();
2223
24+
type GraphRange = {
25+
start: string;
26+
end: string;
27+
date: Date | null;
28+
};
29+
30+
// How many days are shown in the graph
31+
const DAY_RANGE = 30;
32+
33+
/**
34+
* Calculates the start and end range for a history graph for this benchmark
35+
* and artifact.
36+
*/
37+
function getGraphRange(artifact: ArtifactDescription): GraphRange {
38+
const date = new Date(artifact.date);
39+
40+
// If this is a try commit, we don't know its future, so always we just display
41+
// the last `DAY_RANGE` days.
42+
if (artifact.type === "try") {
43+
return {
44+
start: getPastDate(date, DAY_RANGE),
45+
end: artifact.commit,
46+
date: null,
47+
};
48+
} else {
49+
// If this is a master commit, then we try to display `dayRange` days
50+
// "centered" around the commit date.
51+
52+
// Calculate the end of the range, which is commit date + half of the
53+
// amount of days we want to show. If this date is in the future,
54+
// the server will clip the result at the current date.
55+
const end = getFutureDate(date, DAY_RANGE / 2);
56+
57+
// Calculate how many days there have been from the commit date
58+
const daysInFuture = Math.min(
59+
DAY_RANGE / 2,
60+
daysBetweenDates(date, new Date())
61+
);
62+
63+
// Calculate how many days we should go into the past, taking into account
64+
// the days that will be clipped by the server.
65+
const daysInPast = DAY_RANGE - daysInFuture;
66+
67+
const start = getPastDate(date, daysInPast);
68+
return {
69+
start,
70+
end,
71+
date,
72+
};
73+
}
74+
}
75+
76+
/**
77+
* Hook into the uPlot drawing machinery to draw a vertical line at the
78+
* position of the given `date`.
79+
*/
80+
function drawCurrentDate(opts: GraphRenderOpts, date: Date) {
81+
opts.hooks = {
82+
drawSeries: (u: uPlot) => {
83+
let ctx = u.ctx;
84+
ctx.save();
85+
86+
const y0 = u.bbox.top;
87+
const y1 = y0 + u.bbox.height;
88+
const x = u.valToPos(date.getTime() / 1000, "x", true);
89+
90+
ctx.beginPath();
91+
ctx.moveTo(x, y0);
92+
ctx.strokeStyle = "red";
93+
ctx.setLineDash([5, 5]);
94+
ctx.lineTo(x, y1);
95+
ctx.stroke();
96+
97+
ctx.restore();
98+
},
99+
};
100+
}
101+
23102
async function renderGraph() {
103+
const {start, end, date} = graphRange.value;
24104
const selector = {
25105
benchmark: props.testCase.benchmark,
26106
profile: props.testCase.profile,
27107
scenario: props.testCase.scenario,
28108
stat: props.metric,
29-
start: getDateInPast(props.artifact),
30-
end: props.artifact.commit,
109+
start,
110+
end,
31111
// We want to be able to see noise "blips" vs. a previous artifact.
32112
// The "percent relative from previous commit" graph should be the best to
33113
// see these kinds of changes.
34114
kind: "percentrelative" as GraphKind,
35115
};
36116
const graphData = await GRAPH_RESOLVER.loadGraph(selector);
37-
renderPlots(graphData, selector, chartElement.value, {
117+
const opts: GraphRenderOpts = {
38118
renderTitle: false,
39-
});
119+
};
120+
if (date !== null) {
121+
drawCurrentDate(opts, date);
122+
}
123+
renderPlots(graphData, selector, chartElement.value, opts);
124+
}
125+
126+
function getGraphTitle() {
127+
const {start, end, date} = graphRange.value;
128+
const msg = `${DAY_RANGE} day history`;
129+
if (date !== null) {
130+
return `${msg} (${start} - ${end})`;
131+
} else {
132+
return `${msg} (up to benchmarked commit)`;
133+
}
40134
}
41135
42136
const metadata = computed(
@@ -58,6 +152,7 @@ const cargoProfile = computed((): CargoProfileMetadata => {
58152
});
59153
60154
const chartElement: Ref<HTMLElement | null> = ref(null);
155+
const graphRange = computed(() => getGraphRange(props.artifact));
61156
62157
onMounted(() => renderGraph());
63158
</script>
@@ -113,7 +208,7 @@ onMounted(() => renderGraph());
113208
</div>
114209
<div>
115210
<div class="title">
116-
<div class="bold">30 day history (up to benchmarked commit)</div>
211+
<div class="bold">{{ getGraphTitle() }}</div>
117212
<div style="font-size: 0.8em">
118213
Each plotted value is relative to its previous commit
119214
</div>

site/frontend/src/pages/compare/compile/table/comparisons-table.vue

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {CompileBenchmarkMap, CompileTestCase} from "../common";
77
import {computed} from "vue";
88
import {useExpandedStore} from "./expansion";
99
import BenchmarkDetail from "./benchmark-detail.vue";
10-
import {getDateInPast} from "./utils";
10+
import {getPastDate} from "./utils";
1111
1212
const props = defineProps<{
1313
id: string;
@@ -29,7 +29,8 @@ function graphLink(
2929
stat: string,
3030
comparison: TestCaseComparison<CompileTestCase>
3131
): string {
32-
const start = getDateInPast(commit);
32+
// Move to `30 days ago` to display history of the test case
33+
const start = getPastDate(new Date(commit.date), 30);
3334
const end = commit.commit;
3435
const {benchmark, profile, scenario} = comparison.testCase;
3536
return `/index.html?start=${start}&end=${end}&benchmark=${benchmark}&profile=${profile}&scenario=${scenario}&stat=${stat}`;
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1-
import {ArtifactDescription} from "../../types";
1+
/**
2+
* Returns a date that is the given days in the past from the passed `date`.
3+
*/
4+
export function getPastDate(date: Date, days: number): string {
5+
const past = new Date(date.getTime());
6+
past.setUTCDate(date.getUTCDate() - days);
7+
return format_ymd(past);
8+
}
29

310
/**
4-
* Returns a date in the past for which we want to display a historical chart.
11+
* Returns a date that is the given days in the future from the passed `date`.
512
*/
6-
export function getDateInPast(artifact: ArtifactDescription): string {
7-
const date = new Date(artifact.date);
8-
// Move to `30 days ago` to display history of the test case
9-
date.setUTCDate(date.getUTCDate() - 30);
13+
export function getFutureDate(date: Date, days: number): string {
14+
const future = new Date(date.getTime());
15+
future.setUTCDate(date.getUTCDate() + days);
16+
return format_ymd(future);
17+
}
18+
19+
function format_ymd(date: Date): string {
1020
const year = date.getUTCFullYear();
1121
const month = (date.getUTCMonth() + 1).toString().padStart(2, "0");
1222
const day = date.getUTCDate().toString().padStart(2, "0");
1323
return `${year}-${month}-${day}`;
1424
}
25+
26+
/**
27+
* Calculates the number of (whole) days between the two days.
28+
*/
29+
export function daysBetweenDates(a: Date, b: Date): number {
30+
return Math.floor((b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24));
31+
}

0 commit comments

Comments
 (0)