Skip to content

Commit 05b98de

Browse files
authored
Merge pull request #1690 from Kobzol/benchmark-detail-graph
Add history graph to benchmark detail
2 parents f38de3c + f92b547 commit 05b98de

File tree

13 files changed

+349
-85
lines changed

13 files changed

+349
-85
lines changed

site/frontend/src/graph/api.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {GraphData, GraphsSelector} from "./data";
2+
import {getJson} from "../utils/requests";
3+
import {GRAPH_DATA_URL} from "../urls";
4+
5+
export async function loadGraphs(selector: GraphsSelector): Promise<GraphData> {
6+
const params = {
7+
start: selector.start,
8+
end: selector.end,
9+
kind: selector.kind as string,
10+
stat: selector.stat,
11+
benchmark: selector.benchmark,
12+
scenario: selector.scenario,
13+
profile: selector.profile,
14+
};
15+
return await getJson<GraphData>(GRAPH_DATA_URL, params);
16+
}

site/frontend/src/pages/graphs/plots.ts renamed to site/frontend/src/graph/render.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import uPlot, {TypedArray} from "uplot";
2-
import {GraphData, GraphsSelector} from "./state";
2+
import {GraphData, GraphsSelector} from "./data";
33

44
const commonCacheStateColors = {
55
full: "#7cb5ec",
@@ -148,7 +148,6 @@ function tooltipPlugin({
148148
}
149149

150150
function genPlotOpts({
151-
title,
152151
width,
153152
height,
154153
yAxisLabel,
@@ -159,9 +158,9 @@ function genPlotOpts({
159158
alpha = 0.3,
160159
prox = 5,
161160
absoluteMode,
161+
hooks,
162162
}) {
163163
return {
164-
title,
165164
width,
166165
height,
167166
series,
@@ -239,6 +238,7 @@ function genPlotOpts({
239238
ctx.stroke();
240239
},
241240
],
241+
...hooks,
242242
},
243243
},
244244
tooltipPlugin({
@@ -280,13 +280,22 @@ function normalizeData(data: GraphData) {
280280
}
281281
}
282282

283-
// Renders the plots data with the given parameters from the `selector`, into a DOM node optionally
284-
// selected by the `elementSelector` query.
283+
export type GraphRenderOpts = {
284+
renderTitle?: boolean;
285+
hooks?: {drawSeries: (uPlot, number) => void};
286+
};
287+
288+
// Renders the plots data with the given parameters from the `selector` into
289+
// the passed DOM element.
285290
export function renderPlots(
286291
data: GraphData,
287292
selector: GraphsSelector,
288-
elementSelector: string
293+
plotElement: HTMLElement,
294+
opts?: GraphRenderOpts
289295
) {
296+
const renderTitle = opts?.renderTitle ?? true;
297+
const hooks = opts?.hooks ?? {};
298+
290299
normalizeData(data);
291300

292301
const names = Object.keys(data.benchmarks).sort();
@@ -364,7 +373,6 @@ export function renderPlots(
364373
cacheStates[Object.keys(cacheStates)[0]].interpolated_indices;
365374

366375
let plotOpts = genPlotOpts({
367-
title: benchName + "-" + benchKind,
368376
width: Math.floor(window.innerWidth / 4) - 40,
369377
height: 300,
370378
yAxisLabel,
@@ -375,13 +383,13 @@ export function renderPlots(
375383
return indices.has(dataIdx);
376384
},
377385
absoluteMode: selector.kind == "raw",
386+
hooks,
378387
});
388+
if (renderTitle) {
389+
plotOpts["title"] = `${benchName}-${benchKind}`;
390+
}
379391

380-
new uPlot(
381-
plotOpts,
382-
plotData as any as TypedArray[],
383-
document.querySelector<HTMLElement>(elementSelector)
384-
);
392+
new uPlot(plotOpts, plotData as any as TypedArray[], plotElement);
385393

386394
i++;
387395
}

site/frontend/src/graph/resolver.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {GraphData, GraphsSelector} from "./data";
2+
import {loadGraphs} from "./api";
3+
4+
/**
5+
* Graph API resolver that contains a cache of downloaded graphs.
6+
* This is important for Vue components that download a graph on mount.
7+
* Without a cache, they would download a graph each time they are destroyed
8+
* and recreated.
9+
*/
10+
export class GraphResolver {
11+
private cache: Dict<GraphData> = {};
12+
13+
public async loadGraph(selector: GraphsSelector): Promise<GraphData> {
14+
const key = `${selector.benchmark};${selector.profile};${selector.scenario};${selector.start};${selector.end};${selector.stat};${selector.kind}`;
15+
if (!this.cache.hasOwnProperty(key)) {
16+
this.cache[key] = await loadGraphs(selector);
17+
}
18+
19+
return this.cache[key];
20+
}
21+
}
22+
23+
/**
24+
* This is essentially a global variable, but it makes the code simpler and
25+
* since we currently don't have any unit tests, we don't really need to avoid
26+
* global variables that much. If needed, it could be provided to Vue components
27+
* from a parent via props or context.
28+
*/
29+
export const GRAPH_RESOLVER = new GraphResolver();

0 commit comments

Comments
 (0)