Skip to content

Commit 47972d8

Browse files
authored
Merge pull request #1620 from Kobzol/runtime-ui
Add basic runtime UI
2 parents 0daf232 + 187c95b commit 47972d8

24 files changed

+995
-568
lines changed

site/frontend/src/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ export interface BenchmarkInfo {
88
as_of: string | null;
99
}
1010

11-
export async function loadBenchmarkInfo() {
11+
export async function loadBenchmarkInfo(): Promise<BenchmarkInfo> {
1212
return await getJson<BenchmarkInfo>(INFO_URL);
1313
}

site/frontend/src/pages/compare/bootstrap-table.vue renamed to site/frontend/src/pages/compare/bootstrap/bootstrap-table.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
2-
import {CompareResponse} from "./types";
3-
import {diffClass, percentClass} from "./shared";
2+
import {CompareResponse} from "../types";
3+
import {diffClass, percentClass} from "../shared";
44
55
const props = defineProps<{data: CompareResponse}>();
66

site/frontend/src/pages/compare/summary/aggregations.vue renamed to site/frontend/src/pages/compare/compile/aggregations.vue

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
<script setup lang="ts">
2-
import {computeSummary, SummaryGroup, TestCase} from "../data";
2+
import {computeSummary, SummaryGroup, TestCaseComparison} from "../data";
33
import Toggle from "../toggle.vue";
4-
import SummaryTable from "./summary-table.vue";
4+
import SummaryTable from "../summary/summary-table.vue";
55
import {createPersistedRef} from "../../../storage";
66
import {PREF_AGGREGATIONS_OPENED} from "../prefs";
7+
import {CompileTestCase} from "./common";
78
89
const props = defineProps<{
9-
cases: TestCase[];
10+
cases: TestCaseComparison<CompileTestCase>[];
1011
}>();
1112
1213
function calculateSummary(
13-
keyAttribute: string,
14+
keyAttribute: keyof CompileTestCase,
1415
keyValue: string
1516
): SummaryGroup {
1617
const benchmarks = [];
1718
for (const benchmark of props.cases) {
18-
if (benchmark[keyAttribute].startsWith(keyValue)) {
19+
if (benchmark.testCase[keyAttribute].startsWith(keyValue)) {
1920
benchmarks.push(benchmark);
2021
}
2122
}

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

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
<script setup lang="tsx">
22
import {computed, h} from "vue";
3-
import TestCasesTable from "./test-cases-table.vue";
4-
import {TestCase} from "../data";
5-
import {CompareResponse, DataFilter} from "../types";
3+
import ComparisonsTable from "./comparisons-table.vue";
4+
import {TestCaseComparison} from "../data";
5+
import {CompareResponse} from "../types";
6+
import {CompileBenchmarkFilter, CompileTestCase} from "./common";
67
78
export interface BenchmarkProps {
89
data: CompareResponse;
9-
testCases: TestCase[];
10-
allTestCases: TestCase[];
11-
filter: DataFilter;
10+
testCases: TestCaseComparison<CompileTestCase>[];
11+
allTestCases: TestCaseComparison<CompileTestCase>[];
12+
filter: CompileBenchmarkFilter;
1213
stat: string;
1314
}
1415
@@ -35,16 +36,20 @@ function Section({
3536
}
3637
3738
const primaryCases = computed(() =>
38-
props.testCases.filter((c) => c.category === "primary")
39+
props.testCases.filter((c) => c.testCase.category === "primary")
3940
);
4041
const secondaryCases = computed(() =>
41-
props.testCases.filter((c) => c.category === "secondary")
42+
props.testCases.filter((c) => c.testCase.category === "secondary")
4243
);
4344
const primaryHasNonRelevant = computed(
44-
() => props.allTestCases.filter((c) => c.category === "primary").length > 0
45+
() =>
46+
props.allTestCases.filter((c) => c.testCase.category === "primary").length >
47+
0
4548
);
4649
const secondaryHasNonRelevant = computed(
47-
() => props.allTestCases.filter((c) => c.category === "secondary").length > 0
50+
() =>
51+
props.allTestCases.filter((c) => c.testCase.category === "secondary")
52+
.length > 0
4853
);
4954
</script>
5055

@@ -58,9 +63,9 @@ const secondaryHasNonRelevant = computed(
5863
</details>
5964
<hr />
6065
</div>
61-
<TestCasesTable
66+
<ComparisonsTable
6267
id="primary-benchmarks"
63-
:cases="primaryCases"
68+
:comparisons="primaryCases"
6469
:has-non-relevant="primaryHasNonRelevant"
6570
:show-raw-data="filter.showRawData"
6671
:commit-a="data.a"
@@ -70,11 +75,11 @@ const secondaryHasNonRelevant = computed(
7075
<template #header>
7176
<Section title="Primary" link="secondary" :linkUp="false"></Section>
7277
</template>
73-
</TestCasesTable>
78+
</ComparisonsTable>
7479
<hr />
75-
<TestCasesTable
80+
<ComparisonsTable
7681
id="secondary-benchmarks"
77-
:cases="secondaryCases"
82+
:comparisons="secondaryCases"
7883
:has-non-relevant="secondaryHasNonRelevant"
7984
:show-raw-data="filter.showRawData"
8085
:commit-a="data.a"
@@ -84,7 +89,7 @@ const secondaryHasNonRelevant = computed(
8489
<template #header>
8590
<Section title="Secondary" link="primary" :linkUp="true"></Section>
8691
</template>
87-
</TestCasesTable>
92+
</ComparisonsTable>
8893
<br />
8994
<hr />
9095
</div>
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import {BenchmarkFilter, CompareResponse, StatComparison} from "../types";
2+
import {calculateComparison, TestCaseComparison} from "../data";
3+
4+
export type CompileBenchmarkFilter = {
5+
profile: {
6+
check: boolean;
7+
debug: boolean;
8+
opt: boolean;
9+
doc: boolean;
10+
};
11+
scenario: {
12+
full: boolean;
13+
incrFull: boolean;
14+
incrUnchanged: boolean;
15+
incrPatched: boolean;
16+
};
17+
category: {
18+
primary: boolean;
19+
secondary: boolean;
20+
};
21+
} & BenchmarkFilter;
22+
export const defaultCompileFilter: CompileBenchmarkFilter = {
23+
name: null,
24+
nonRelevant: false,
25+
showRawData: false,
26+
profile: {
27+
check: true,
28+
debug: true,
29+
opt: true,
30+
doc: true,
31+
},
32+
scenario: {
33+
full: true,
34+
incrFull: true,
35+
incrUnchanged: true,
36+
incrPatched: true,
37+
},
38+
category: {
39+
primary: true,
40+
secondary: true,
41+
},
42+
};
43+
44+
export type Profile = "check" | "debug" | "opt" | "doc";
45+
export type Category = "primary" | "secondary";
46+
47+
export type CompileBenchmarkMap = Dict<{category: Category}>;
48+
49+
export interface CompileBenchmarkDescription {
50+
name: string;
51+
category: Category;
52+
}
53+
54+
export interface CompileBenchmarkComparison {
55+
benchmark: string;
56+
profile: Profile;
57+
scenario: string;
58+
comparison: StatComparison;
59+
}
60+
61+
export interface CompileTestCase {
62+
benchmark: string;
63+
profile: Profile;
64+
scenario: string;
65+
category: Category;
66+
}
67+
68+
export function computeCompileComparisonsWithNonRelevant(
69+
filter: CompileBenchmarkFilter,
70+
comparisons: CompileBenchmarkComparison[],
71+
benchmarkMap: CompileBenchmarkMap
72+
): TestCaseComparison<CompileTestCase>[] {
73+
function profileFilter(profile: Profile): boolean {
74+
if (profile === "check") {
75+
return filter.profile.check;
76+
} else if (profile === "debug") {
77+
return filter.profile.debug;
78+
} else if (profile === "opt") {
79+
return filter.profile.opt;
80+
} else if (profile === "doc") {
81+
return filter.profile.doc;
82+
} else {
83+
return true;
84+
}
85+
}
86+
87+
function scenarioFilter(scenario: string): boolean {
88+
if (scenario === "full") {
89+
return filter.scenario.full;
90+
} else if (scenario === "incr-full") {
91+
return filter.scenario.incrFull;
92+
} else if (scenario === "incr-unchanged") {
93+
return filter.scenario.incrUnchanged;
94+
} else if (scenario.startsWith("incr-patched")) {
95+
return filter.scenario.incrPatched;
96+
} else {
97+
// Unknown, but by default we should show things
98+
return true;
99+
}
100+
}
101+
102+
function categoryFilter(category: Category) {
103+
if (category === "primary" && !filter.category.primary) return false;
104+
if (category === "secondary" && !filter.category.secondary) return false;
105+
return true;
106+
}
107+
108+
function shouldShowTestCase(comparison: TestCaseComparison<CompileTestCase>) {
109+
const name = `${comparison.testCase.benchmark} ${comparison.testCase.profile} ${comparison.testCase.scenario}`;
110+
const nameFilter = filter.name && filter.name.trim();
111+
const nameFiltered = !nameFilter || name.includes(nameFilter);
112+
113+
return (
114+
profileFilter(comparison.testCase.profile) &&
115+
scenarioFilter(comparison.testCase.scenario) &&
116+
categoryFilter(comparison.testCase.category) &&
117+
nameFiltered
118+
);
119+
}
120+
121+
let filteredComparisons = comparisons
122+
.map(
123+
(c: CompileBenchmarkComparison): TestCaseComparison<CompileTestCase> => {
124+
let testCase = {
125+
benchmark: c.benchmark,
126+
profile: c.profile,
127+
scenario: c.scenario,
128+
category: (benchmarkMap[c.benchmark] || {}).category || "secondary",
129+
};
130+
return calculateComparison(c.comparison, testCase);
131+
}
132+
)
133+
.filter((tc) => shouldShowTestCase(tc));
134+
135+
// Sort by name first, so that there is a canonical ordering
136+
// of test cases. This ensures the overall order is stable, even if
137+
// individual benchmarks have the same largestChange value.
138+
filteredComparisons.sort((a, b) =>
139+
a.testCase.benchmark.localeCompare(b.testCase.benchmark)
140+
);
141+
filteredComparisons.sort((a, b) => Math.abs(b.percent) - Math.abs(a.percent));
142+
143+
return filteredComparisons;
144+
}
145+
146+
export function createCompileBenchmarkMap(
147+
data: CompareResponse
148+
): CompileBenchmarkMap {
149+
const benchmarks = {};
150+
for (const benchmark of data.compile_benchmark_data) {
151+
benchmarks[benchmark.name] = {
152+
category: benchmark.category,
153+
};
154+
}
155+
return benchmarks;
156+
}

0 commit comments

Comments
 (0)