Skip to content

Commit b4b44f0

Browse files
committed
Use benchmark detail endpoint in the UI
1 parent daea104 commit b4b44f0

File tree

5 files changed

+131
-45
lines changed

5 files changed

+131
-45
lines changed

site/frontend/src/graph/data.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface Series {
1818

1919
// Graph data received from the server
2020
export interface GraphData {
21-
commits: [[number, string]];
21+
commits: Array<[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: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import {
55
CompileBenchmarkMetadata,
66
CompileTestCase,
77
} from "../common";
8-
import {computed, onMounted, Ref, ref} from "vue";
8+
import {capitalize, computed, onMounted, Ref, ref} from "vue";
99
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,68 @@ async function renderGraph(kind: GraphKind, chartRef: Ref<HTMLElement | null>) {
116106
stat: props.metric,
117107
start,
118108
end,
119-
kind,
109+
kinds: ["percentrelative", "raw"] as GraphKind[],
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+
// The server returns profiles capitalized, so we need to match that
125+
// here, so that the graph code can find the expected profile.
126+
[capitalize(selector.profile)]: {
127+
[selector.scenario]: detail.graphs[index],
128+
},
129+
},
130+
},
131+
};
132+
const graphSelector = {
133+
benchmark: selector.benchmark,
134+
profile: selector.profile,
135+
scenario: selector.scenario,
136+
stat: selector.stat,
137+
start: selector.start,
138+
end: selector.end,
139+
kind,
140+
};
141+
142+
return [data, graphSelector];
143+
}
144+
145+
const [percentRelativeData, percentRelativeSelector] = buildGraph(
146+
0,
147+
"percentrelative"
148+
);
149+
const [rawData, rawSelector] = buildGraph(1, "raw");
150+
151+
// We want to be able to see noise "blips" vs. a previous artifact.
152+
// The "percent relative from previous commit" graph should be the best to
153+
// see these kinds of changes.
154+
renderGraph(
155+
percentRelativeData,
156+
percentRelativeSelector,
157+
date,
158+
relativeChartElement
159+
);
160+
// We also want to see whether a change maintained its value or whether it was noise and has since
161+
// returned to steady state. Here, an absolute graph ("raw") is best.
162+
renderGraph(rawData, rawSelector, date, absoluteChartElement);
163+
}
164+
165+
async function renderGraph(
166+
graphData: GraphData,
167+
selector: GraphsSelector,
168+
date: Date | null,
169+
chartRef: Ref<HTMLElement | null>
170+
) {
122171
const opts: GraphRenderOpts = {
123172
width: Math.min(window.innerWidth - 40, 465),
124173
renderTitle: false,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {GraphKind, Series} from "../../../../graph/data";
2+
import {getJson} from "../../../../utils/requests";
3+
import {COMPARE_COMPILE_DETAIL_DATA_URL} from "../../../../urls";
4+
5+
export interface CompileDetailSelector {
6+
start: string;
7+
end: string;
8+
stat: string;
9+
benchmark: string;
10+
scenario: string;
11+
profile: string;
12+
kinds: GraphKind[];
13+
}
14+
15+
// Compile benchmark detail received from the server
16+
export interface CompileDetail {
17+
commits: Array<[number, string]>;
18+
// One Series for each GraphKind in the CompileDetailSelector
19+
graphs: Series[];
20+
}
21+
22+
/**
23+
* Compile benchmark detail resolver that contains a cache of downloaded details.
24+
* This is important for Vue components that download the benchmark detail on mount.
25+
* Without a cache, they would download the detail each time they are destroyed
26+
* and recreated.
27+
*/
28+
export class CompileBenchmarkDetailResolver {
29+
private cache: Dict<CompileDetail> = {};
30+
31+
public async loadDetail(
32+
selector: CompileDetailSelector
33+
): Promise<CompileDetail> {
34+
const key = `${selector.benchmark};${selector.profile};${selector.scenario};${selector.start};${selector.end};${selector.stat};${selector.kinds}`;
35+
if (!this.cache.hasOwnProperty(key)) {
36+
this.cache[key] = await loadDetail(selector);
37+
}
38+
39+
return this.cache[key];
40+
}
41+
}
42+
43+
/**
44+
* This is essentially a global variable, but it makes the code simpler and
45+
* since we currently don't have any unit tests, we don't really need to avoid
46+
* global variables that much. If needed, it could be provided to Vue components
47+
* from a parent via props or context.
48+
*/
49+
export const COMPILE_DETAIL_RESOLVER = new CompileBenchmarkDetailResolver();
50+
51+
async function loadDetail(
52+
selector: CompileDetailSelector
53+
): Promise<CompileDetail> {
54+
const params = {
55+
start: selector.start,
56+
end: selector.end,
57+
stat: selector.stat,
58+
benchmark: selector.benchmark,
59+
scenario: selector.scenario,
60+
profile: selector.profile,
61+
kinds: selector.kinds.join(","),
62+
};
63+
return await getJson<CompileDetail>(COMPARE_COMPILE_DETAIL_DATA_URL, params);
64+
}

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)