Skip to content

Commit 008f9b0

Browse files
committed
Use benchmark detail endpoint in the UI
1 parent 616d3a6 commit 008f9b0

File tree

5 files changed

+128
-43
lines changed

5 files changed

+128
-43
lines changed

site/frontend/src/graph/data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ export interface Series {
1919
// Graph data received from the server
2020
export interface GraphData {
2121
commits: [[number, string]];
22+
// benchmark -> profile -> scenario -> series
2223
benchmarks: Dict<Dict<Dict<Series>>>;
2324
}

site/frontend/src/graph/resolver.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

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

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import Tooltip from "../../tooltip.vue";
1010
import {ArtifactDescription} from "../../types";
1111
import {daysBetweenDates, getFutureDate, getPastDate} from "./utils";
1212
import {GraphRenderOpts, renderPlots} from "../../../../graph/render";
13-
import {GRAPH_RESOLVER} from "../../../../graph/resolver";
14-
import {GraphKind} from "../../../../graph/data";
13+
import {GraphData, GraphKind, GraphsSelector} from "../../../../graph/data";
1514
import uPlot from "uplot";
1615
import CachegrindCmd from "../../../../components/cachegrind-cmd.vue";
16+
import {COMPILE_DETAIL_RESOLVER} from "./detail-resolver";
1717
1818
const props = defineProps<{
1919
testCase: CompileTestCase;
@@ -98,16 +98,6 @@ function drawCurrentDate(opts: GraphRenderOpts, date: Date) {
9898
9999
// Render both relative and absolute graphs
100100
async function renderGraphs() {
101-
// We want to be able to see noise "blips" vs. a previous artifact.
102-
// The "percent relative from previous commit" graph should be the best to
103-
// see these kinds of changes.
104-
renderGraph("percentrelative" as GraphKind, relativeChartElement);
105-
// We also want to see whether a change maintained its value or whether it was noise and has since
106-
// returned to steady state. Here, an absolute graph ("raw") is best.
107-
renderGraph("raw" as GraphKind, absoluteChartElement);
108-
}
109-
110-
async function renderGraph(kind: GraphKind, chartRef: Ref<HTMLElement | null>) {
111101
const {start, end, date} = graphRange.value;
112102
const selector = {
113103
benchmark: props.testCase.benchmark,
@@ -116,9 +106,66 @@ async function renderGraph(kind: GraphKind, chartRef: Ref<HTMLElement | null>) {
116106
stat: props.metric,
117107
start,
118108
end,
119-
kind,
109+
kinds: ["percentrelative", "raw"],
120110
};
121-
const graphData = await GRAPH_RESOLVER.loadGraph(selector);
111+
const detail = await COMPILE_DETAIL_RESOLVER.loadDetail(selector);
112+
if (detail.commits.length === 0) {
113+
return;
114+
}
115+
116+
function buildGraph(
117+
index: number,
118+
kind: GraphKind
119+
): [GraphData, GraphsSelector] {
120+
const data = {
121+
commits: detail.commits,
122+
benchmarks: {
123+
[selector.benchmark]: {
124+
[selector.profile]: {
125+
[selector.scenario]: detail.graphs[index],
126+
},
127+
},
128+
},
129+
};
130+
const graphSelector = {
131+
benchmark: selector.benchmark,
132+
profile: selector.profile,
133+
scenario: selector.scenario,
134+
stat: selector.stat,
135+
start: selector.start,
136+
end: selector.end,
137+
kind,
138+
};
139+
140+
return [data, graphSelector];
141+
}
142+
143+
const [percentRelativeData, percentRelativeSelector] = buildGraph(
144+
0,
145+
"percentrelative"
146+
);
147+
const [rawData, rawSelector] = buildGraph(0, "raw");
148+
149+
// We want to be able to see noise "blips" vs. a previous artifact.
150+
// The "percent relative from previous commit" graph should be the best to
151+
// see these kinds of changes.
152+
renderGraph(
153+
percentRelativeData,
154+
percentRelativeSelector,
155+
date,
156+
relativeChartElement
157+
);
158+
// We also want to see whether a change maintained its value or whether it was noise and has since
159+
// returned to steady state. Here, an absolute graph ("raw") is best.
160+
renderGraph(rawData, rawSelector, date, absoluteChartElement);
161+
}
162+
163+
async function renderGraph(
164+
graphData: GraphData,
165+
selector: GraphsSelector,
166+
date: Date | null,
167+
chartRef: Ref<HTMLElement | null>
168+
) {
122169
const opts: GraphRenderOpts = {
123170
width: Math.min(window.innerWidth - 40, 465),
124171
renderTitle: false,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import {GraphKind} from "../../../../graph/data";
2+
import {Series} from "uplot";
3+
import {getJson} from "../../../../utils/requests";
4+
import {COMPARE_COMPILE_DETAIL_DATA_URL} from "../../../../urls";
5+
6+
export interface CompileDetailSelector {
7+
start: string;
8+
end: string;
9+
stat: string;
10+
benchmark: string;
11+
scenario: string;
12+
profile: string;
13+
kinds: GraphKind[];
14+
}
15+
16+
// Compile benchmark detail received from the server
17+
export interface CompileDetail {
18+
commits: [[number, string]];
19+
// One Series for each GraphKind in the CompileDetailSelector
20+
graphs: Series[];
21+
}
22+
23+
/**
24+
* Compile benchmark detail resolver that contains a cache of downloaded details.
25+
* This is important for Vue components that download the benchmark detail on mount.
26+
* Without a cache, they would download the detail each time they are destroyed
27+
* and recreated.
28+
*/
29+
export class CompileBenchmarkDetailResolver {
30+
private cache: Dict<CompileDetail> = {};
31+
32+
public async loadDetail(
33+
selector: CompileDetailSelector
34+
): Promise<CompileDetail> {
35+
const key = `${selector.benchmark};${selector.profile};${selector.scenario};${selector.start};${selector.end};${selector.stat};${selector.kinds}`;
36+
if (!this.cache.hasOwnProperty(key)) {
37+
this.cache[key] = await loadDetail(selector);
38+
}
39+
40+
return this.cache[key];
41+
}
42+
}
43+
44+
/**
45+
* This is essentially a global variable, but it makes the code simpler and
46+
* since we currently don't have any unit tests, we don't really need to avoid
47+
* global variables that much. If needed, it could be provided to Vue components
48+
* from a parent via props or context.
49+
*/
50+
export const COMPILE_DETAIL_RESOLVER = new CompileBenchmarkDetailResolver();
51+
52+
async function loadDetail(
53+
selector: CompileDetailSelector
54+
): Promise<CompileDetail> {
55+
const params = {
56+
start: selector.start,
57+
end: selector.end,
58+
stat: selector.stat,
59+
benchmark: selector.benchmark,
60+
scenario: selector.scenario,
61+
profile: selector.profile,
62+
kinds: selector.kinds,
63+
};
64+
return await getJson<CompileDetail>(COMPARE_COMPILE_DETAIL_DATA_URL, params);
65+
}

site/frontend/src/urls.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export const STATUS_DATA_URL = `${BASE_URL}/status_page`;
77
export const BOOTSTRAP_DATA_URL = `${BASE_URL}/bootstrap`;
88
export const GRAPH_DATA_URL = `${BASE_URL}/graphs`;
99
export const COMPARE_DATA_URL = `${BASE_URL}/get`;
10+
export const COMPARE_COMPILE_DETAIL_DATA_URL = `${BASE_URL}/compare-compile-detail`;
1011
export const SELF_PROFILE_DATA_URL = `${BASE_URL}/self-profile`;

0 commit comments

Comments
 (0)