Skip to content

Commit 0695b84

Browse files
authored
Merge pull request #2010 from rust-lang/compare-backends
Add UI for comparing backend results
2 parents e6488b4 + acc2d3c commit 0695b84

File tree

4 files changed

+123
-4
lines changed

4 files changed

+123
-4
lines changed

site/frontend/src/pages/compare/compile/benchmarks.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface BenchmarkProps {
1616
benchmarkMap: CompileBenchmarkMap;
1717
filter: CompileBenchmarkFilter;
1818
stat: string;
19+
showBackend: boolean;
1920
}
2021
2122
const props = defineProps<BenchmarkProps>();
@@ -77,6 +78,7 @@ const secondaryHasNonRelevant = computed(
7778
:commit-b="data.b"
7879
:stat="stat"
7980
:benchmark-map="benchmarkMap"
81+
:show-backend="showBackend"
8082
>
8183
<template #header>
8284
<Section title="Primary" link="secondary" :linkUp="false"></Section>
@@ -92,6 +94,7 @@ const secondaryHasNonRelevant = computed(
9294
:commit-b="data.b"
9395
:stat="stat"
9496
:benchmark-map="benchmarkMap"
97+
:show-backend="showBackend"
9598
>
9699
<template #header>
97100
<Section title="Secondary" link="primary" :linkUp="true"></Section>

site/frontend/src/pages/compare/compile/common.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type CompileBenchmarkFilter = {
2727
binary: boolean;
2828
library: boolean;
2929
};
30+
selfCompareBackend: boolean;
3031
} & BenchmarkFilter;
3132

3233
export const defaultCompileFilter: CompileBenchmarkFilter = {
@@ -57,6 +58,7 @@ export const defaultCompileFilter: CompileBenchmarkFilter = {
5758
binary: true,
5859
library: true,
5960
},
61+
selfCompareBackend: false,
6062
};
6163

6264
export type Profile = "check" | "debug" | "opt" | "doc";
@@ -206,5 +208,57 @@ export function createCompileBenchmarkMap(
206208
}
207209

208210
export function testCaseKey(testCase: CompileTestCase): string {
209-
return `${testCase.benchmark};${testCase.profile};${testCase.scenario};${testCase.category}`;
211+
return `${testCase.benchmark};${testCase.profile};${testCase.scenario};${testCase.backend};${testCase.category}`;
212+
}
213+
214+
// Transform compile comparisons to compare LLVM vs Cranelift, instead of
215+
// before/after. Assumes that the data comes from the same commit.
216+
export function transformDataForBackendComparison(
217+
comparisons: CompileBenchmarkComparison[]
218+
): CompileBenchmarkComparison[] {
219+
const benchmarkMap: Map<
220+
string,
221+
{
222+
llvm: number | null;
223+
cranelift: number | null;
224+
benchmark: string;
225+
profile: Profile;
226+
scenario: string;
227+
}
228+
> = new Map();
229+
for (const comparison of comparisons) {
230+
const key = `${comparison.benchmark};${comparison.profile};${comparison.scenario}`;
231+
if (!benchmarkMap.has(key)) {
232+
benchmarkMap.set(key, {
233+
llvm: null,
234+
cranelift: null,
235+
benchmark: comparison.benchmark,
236+
profile: comparison.profile,
237+
scenario: comparison.scenario,
238+
});
239+
}
240+
const record = benchmarkMap.get(key);
241+
if (comparison.backend === "llvm") {
242+
record.llvm = comparison.comparison.statistics[0];
243+
} else if (comparison.backend === "cranelift") {
244+
record.cranelift = comparison.comparison.statistics[0];
245+
}
246+
}
247+
248+
return Array.from(benchmarkMap, ([_, entry]) => {
249+
const comparison: CompileBenchmarkComparison = {
250+
benchmark: entry.benchmark,
251+
profile: entry.profile,
252+
scenario: entry.scenario,
253+
// Treat LLVM as the baseline
254+
backend: "llvm",
255+
comparison: {
256+
statistics: [entry.llvm, entry.cranelift],
257+
is_relevant: true,
258+
significance_factor: 1.0,
259+
significance_threshold: 1.0,
260+
},
261+
};
262+
return comparison;
263+
});
210264
}

site/frontend/src/pages/compare/compile/compile-page.vue

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
computeCompileComparisonsWithNonRelevant,
1515
createCompileBenchmarkMap,
1616
defaultCompileFilter,
17+
transformDataForBackendComparison,
1718
} from "./common";
1819
import {BenchmarkInfo} from "../../../api";
1920
import {importantCompileMetrics} from "../metrics";
@@ -101,6 +102,11 @@ function loadFilterFromUrl(
101102
defaultFilter.artifact.library
102103
),
103104
},
105+
selfCompareBackend: getBoolOrDefault(
106+
urlParams,
107+
"selfCompareBackend",
108+
defaultFilter.selfCompareBackend
109+
),
104110
};
105111
}
106112
@@ -172,6 +178,11 @@ function storeFilterToUrl(
172178
filter.artifact.library,
173179
defaultFilter.artifact.library
174180
);
181+
storeOrReset(
182+
"selfCompareBackend",
183+
filter.selfCompareBackend,
184+
defaultFilter.selfCompareBackend
185+
);
175186
176187
changeUrl(urlParams);
177188
}
@@ -182,6 +193,13 @@ function updateFilter(newFilter: CompileBenchmarkFilter) {
182193
refreshQuickLinks();
183194
}
184195
196+
// We pass the event target here, because Parcel cannot handle the `as`
197+
// cast directly in the template.
198+
function updateSelfCompareBackend(target: EventTarget) {
199+
const element = target as HTMLInputElement;
200+
updateFilter({...filter.value, selfCompareBackend: element.checked});
201+
}
202+
185203
/**
186204
* When the filter changes, the URL is updated.
187205
* After that happens, we want to re-render the quick links component, because
@@ -197,15 +215,36 @@ const urlParams = getUrlParams();
197215
const quickLinksKey = ref(0);
198216
const filter = ref(loadFilterFromUrl(urlParams, defaultCompileFilter));
199217
218+
// Should we use the backend as the source of before/after data?
219+
const selfCompareBackend = computed(() => {
220+
return canCompareBackends.value && filter.value.selfCompareBackend;
221+
});
222+
const canCompareBackends = computed(() => {
223+
const hasMultipleBackends =
224+
new Set(props.data.compile_comparisons.map((c) => c.backend)).size > 1;
225+
// Are we currently comparing the same commit in the before/after toolchains?
226+
const comparesSameCommit = props.data.a.commit === props.data.b.commit;
227+
return hasMultipleBackends && comparesSameCommit;
228+
});
229+
200230
function exportData() {
201231
exportToMarkdown(comparisons.value, filter.value.showRawData);
202232
}
203233
204234
const benchmarkMap = createCompileBenchmarkMap(props.data);
235+
236+
const compileComparisons = computed(() => {
237+
// If requested, artificially restructure the data to create a comparison between backends
238+
if (selfCompareBackend.value) {
239+
return transformDataForBackendComparison(props.data.compile_comparisons);
240+
} else {
241+
return props.data.compile_comparisons;
242+
}
243+
});
205244
const allComparisons = computed(() =>
206245
computeCompileComparisonsWithNonRelevant(
207246
filter.value,
208-
props.data.compile_comparisons,
247+
compileComparisons.value,
209248
benchmarkMap
210249
)
211250
);
@@ -222,6 +261,17 @@ const filteredSummary = computed(() => computeSummary(comparisons.value));
222261
:selected-metric="selector.stat"
223262
:metrics="benchmarkInfo.compile_metrics"
224263
/>
264+
<div
265+
v-if="canCompareBackends"
266+
:title="`Compare codegen backends for commit '${props.data.a.commit}'`"
267+
>
268+
Compare codegen backends for this commit:
269+
<input
270+
type="checkbox"
271+
:checked="selfCompareBackend"
272+
@change="(e) => updateSelfCompareBackend(e.target)"
273+
/>
274+
</div>
225275
<Filters
226276
:defaultFilter="defaultCompileFilter"
227277
:initialFilter="filter"
@@ -230,12 +280,23 @@ const filteredSummary = computed(() => computeSummary(comparisons.value));
230280
/>
231281
<OverallSummary :summary="filteredSummary" />
232282
<Aggregations :cases="comparisons" />
283+
<div class="warning" v-if="selfCompareBackend">
284+
Note: comparing results of the baseline LLVM backend to the Cranelift
285+
backend.
286+
</div>
233287
<Benchmarks
234288
:data="data"
235289
:test-cases="comparisons"
236290
:all-test-cases="allComparisons"
237291
:filter="filter"
238292
:stat="selector.stat"
239293
:benchmark-map="benchmarkMap"
294+
:show-backend="!selfCompareBackend"
240295
></Benchmarks>
241296
</template>
297+
<style lang="scss" scoped>
298+
.warning {
299+
color: red;
300+
font-weight: bold;
301+
}
302+
</style>

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const props = defineProps<{
1818
commitA: ArtifactDescription;
1919
commitB: ArtifactDescription;
2020
stat: string;
21+
showBackend: boolean;
2122
}>();
2223
2324
function prettifyRawNumber(number: number): string {
@@ -56,7 +57,7 @@ const unit = computed(() => {
5657
<th>Benchmark</th>
5758
<th>Profile</th>
5859
<th>Scenario</th>
59-
<th>Backend</th>
60+
<th v-if="showBackend">Backend</th>
6061
<th>% Change</th>
6162
<th class="narrow">
6263
Significance Threshold
@@ -95,7 +96,7 @@ const unit = computed(() => {
9596
{{ comparison.testCase.profile }}
9697
</td>
9798
<td>{{ comparison.testCase.scenario }}</td>
98-
<td>{{ comparison.testCase.backend }}</td>
99+
<td v-if="showBackend">{{ comparison.testCase.backend }}</td>
99100
<td>
100101
<div class="numeric-aligned">
101102
<span v-bind:class="percentClass(comparison.percent)">

0 commit comments

Comments
 (0)