Skip to content

Commit 42e9168

Browse files
authored
Merge pull request #1749 from Kobzol/fraction-chart
Add a chart showing individual compilation parts to benchmark detail
2 parents 1ac6fb5 + 2de22b2 commit 42e9168

File tree

11 files changed

+588
-89
lines changed

11 files changed

+588
-89
lines changed

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

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,15 @@ import {GraphRenderOpts, renderPlots} from "../../../../graph/render";
1313
import {GraphData, GraphKind, GraphsSelector} from "../../../../graph/data";
1414
import uPlot from "uplot";
1515
import CachegrindCmd from "../../../../components/cachegrind-cmd.vue";
16-
import {COMPILE_DETAIL_RESOLVER} from "./detail-resolver";
16+
import {
17+
COMPILE_DETAIL_GRAPHS_RESOLVER,
18+
COMPILE_DETAIL_SECTIONS_RESOLVER,
19+
CompileDetailGraphs,
20+
CompileDetailGraphsSelector,
21+
CompileDetailSections,
22+
CompileDetailSectionsSelector,
23+
} from "./detail-resolver";
24+
import CompileSectionsChart from "./sections-chart.vue";
1725
import PerfettoLink from "../../../../components/perfetto-link.vue";
1826
1927
const props = defineProps<{
@@ -97,10 +105,9 @@ function drawCurrentDate(opts: GraphRenderOpts, date: Date) {
97105
};
98106
}
99107
100-
// Render both relative and absolute graphs
101-
async function renderGraphs() {
102-
const {start, end, date} = graphRange.value;
103-
const selector = {
108+
function createGraphsSelector(): CompileDetailGraphsSelector {
109+
const {start, end} = graphRange.value;
110+
return {
104111
benchmark: props.testCase.benchmark,
105112
profile: props.testCase.profile,
106113
scenario: props.testCase.scenario,
@@ -109,7 +116,30 @@ async function renderGraphs() {
109116
end,
110117
kinds: ["percentrelative", "raw"] as GraphKind[],
111118
};
112-
const detail = await COMPILE_DETAIL_RESOLVER.loadDetail(selector);
119+
}
120+
121+
async function loadGraphs(): Promise<CompileDetailGraphs> {
122+
return await COMPILE_DETAIL_GRAPHS_RESOLVER.load(createGraphsSelector());
123+
}
124+
125+
function createSectionsSelector(): CompileDetailSectionsSelector {
126+
return {
127+
benchmark: props.testCase.benchmark,
128+
profile: props.testCase.profile,
129+
scenario: props.testCase.scenario,
130+
start: props.baseArtifact.commit,
131+
end: props.artifact.commit,
132+
};
133+
}
134+
135+
async function loadSections(): Promise<CompileDetailSections> {
136+
return await COMPILE_DETAIL_SECTIONS_RESOLVER.load(createSectionsSelector());
137+
}
138+
139+
// Render both relative and absolute graphs
140+
async function renderGraphs(detail: CompileDetailGraphs) {
141+
const selector = createGraphsSelector();
142+
const date = graphRange.value.date;
113143
if (detail.commits.length === 0) {
114144
return;
115145
}
@@ -264,7 +294,15 @@ function changeProfileCommand(event: Event) {
264294
profileCommand.value = target.value as ProfileCommand;
265295
}
266296
267-
onMounted(() => renderGraphs());
297+
const sectionsDetail: Ref<CompileDetailSections | null> = ref(null);
298+
onMounted(() => {
299+
loadGraphs().then((d) => {
300+
renderGraphs(d);
301+
});
302+
loadSections().then((d) => {
303+
sectionsDetail.value = d;
304+
});
305+
});
268306
</script>
269307

270308
<template>
@@ -297,7 +335,7 @@ onMounted(() => renderGraphs());
297335
<tr v-if="(metadata?.iterations ?? null) !== null">
298336
<td>
299337
Iterations
300-
<Tooltip> How many times is the benchmark executed? </Tooltip>
338+
<Tooltip> How many times is the benchmark executed?</Tooltip>
301339
</td>
302340
<td>{{ metadata.iterations }}</td>
303341
</tr>
@@ -391,6 +429,32 @@ onMounted(() => renderGraphs());
391429
<div ref="relativeChartElement"></div>
392430
</div>
393431
</div>
432+
<div class="columns">
433+
<div class="rows grow">
434+
<div class="title bold">
435+
Sections
436+
<Tooltip
437+
>Percentual duration of individual compilation sections. This is a
438+
rough estimate that might not necessarily contain all of the
439+
individual parts of the compilation. The sections are calculated
440+
based on the results of self-profile queries and they are measured
441+
based on wall-time.
442+
</Tooltip>
443+
</div>
444+
<div>
445+
<CompileSectionsChart
446+
v-if="
447+
(sectionsDetail?.before ?? null) !== null &&
448+
(sectionsDetail?.after ?? null) !== null
449+
"
450+
:before="sectionsDetail.before"
451+
:after="sectionsDetail.after"
452+
/>
453+
<span v-else-if="sectionsDetail === null">Loading…</span>
454+
<span v-else>Not available</span>
455+
</div>
456+
</div>
457+
</div>
394458
<div class="command">
395459
<div class="title bold">
396460
Local profiling command<Tooltip>
Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import {GraphKind, Series} from "../../../../graph/data";
22
import {getJson} from "../../../../utils/requests";
3-
import {COMPARE_COMPILE_DETAIL_DATA_URL} from "../../../../urls";
3+
import {
4+
COMPARE_COMPILE_DETAIL_GRAPHS_DATA_URL,
5+
COMPARE_COMPILE_DETAIL_SECTIONS_DATA_URL,
6+
} from "../../../../urls";
7+
import {CachedDataLoader} from "./utils";
48

5-
export interface CompileDetailSelector {
9+
export interface CompileDetailGraphsSelector {
610
start: string;
711
end: string;
812
stat: string;
@@ -13,44 +17,58 @@ export interface CompileDetailSelector {
1317
}
1418

1519
// Compile benchmark detail received from the server
16-
export interface CompileDetail {
20+
export interface CompileDetailGraphs {
1721
commits: Array<[number, string]>;
1822
// One Series for each GraphKind in the CompileDetailSelector
1923
graphs: Series[];
24+
sections_before: CompilationSections | null;
25+
sections_after: CompilationSections | null;
2026
}
2127

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> = {};
28+
export interface CompileDetailSectionsSelector {
29+
start: string;
30+
end: string;
31+
benchmark: string;
32+
scenario: string;
33+
profile: string;
34+
}
3035

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-
}
36+
export interface CompileDetailSections {
37+
before: CompilationSections | null;
38+
after: CompilationSections | null;
39+
}
40+
41+
export interface CompilationSection {
42+
name: string;
43+
value: number;
44+
}
3845

39-
return this.cache[key];
40-
}
46+
export interface CompilationSections {
47+
sections: CompilationSection[];
4148
}
4249

4350
/**
51+
* Compile benchmark detail resolver that contains a cache of downloaded details.
52+
* This is important for Vue components that download the benchmark detail on mount.
53+
* Without a cache, they would download the detail each time they are destroyed
54+
* and recreated.
4455
* This is essentially a global variable, but it makes the code simpler and
4556
* since we currently don't have any unit tests, we don't really need to avoid
4657
* global variables that much. If needed, it could be provided to Vue components
4758
* from a parent via props or context.
4859
*/
49-
export const COMPILE_DETAIL_RESOLVER = new CompileBenchmarkDetailResolver();
60+
export const COMPILE_DETAIL_GRAPHS_RESOLVER: CachedDataLoader<
61+
CompileDetailGraphsSelector,
62+
CompileDetailGraphs
63+
> = new CachedDataLoader(
64+
(key: CompileDetailGraphsSelector) =>
65+
`${key.benchmark};${key.profile};${key.scenario};${key.start};${key.end};${key.stat};${key.kinds}`,
66+
loadGraphsDetail
67+
);
5068

51-
async function loadDetail(
52-
selector: CompileDetailSelector
53-
): Promise<CompileDetail> {
69+
async function loadGraphsDetail(
70+
selector: CompileDetailGraphsSelector
71+
): Promise<CompileDetailGraphs> {
5472
const params = {
5573
start: selector.start,
5674
end: selector.end,
@@ -60,5 +78,34 @@ async function loadDetail(
6078
profile: selector.profile,
6179
kinds: selector.kinds.join(","),
6280
};
63-
return await getJson<CompileDetail>(COMPARE_COMPILE_DETAIL_DATA_URL, params);
81+
return await getJson<CompileDetailGraphs>(
82+
COMPARE_COMPILE_DETAIL_GRAPHS_DATA_URL,
83+
params
84+
);
85+
}
86+
87+
// The same thing, but for sections
88+
export const COMPILE_DETAIL_SECTIONS_RESOLVER: CachedDataLoader<
89+
CompileDetailSectionsSelector,
90+
CompileDetailSections
91+
> = new CachedDataLoader(
92+
(key: CompileDetailGraphsSelector) =>
93+
`${key.benchmark};${key.profile};${key.scenario};${key.start};${key.end}`,
94+
loadSectionsDetail
95+
);
96+
97+
async function loadSectionsDetail(
98+
selector: CompileDetailSectionsSelector
99+
): Promise<CompileDetailSections> {
100+
const params = {
101+
start: selector.start,
102+
end: selector.end,
103+
benchmark: selector.benchmark,
104+
scenario: selector.scenario,
105+
profile: selector.profile,
106+
};
107+
return await getJson<CompileDetailSections>(
108+
COMPARE_COMPILE_DETAIL_SECTIONS_DATA_URL,
109+
params
110+
);
64111
}

0 commit comments

Comments
 (0)