Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bfb4a9d

Browse files
committed
Add summary to runtime tab
1 parent 0d5b048 commit bfb4a9d

File tree

7 files changed

+152
-75
lines changed

7 files changed

+152
-75
lines changed

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

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {BenchmarkFilter, CompareResponse, StatComparison} from "../types";
2-
import {TestCaseComparison} from "../data";
2+
import {calculateComparison, TestCaseComparison} from "../data";
33

44
export type CompileBenchmarkFilter = {
55
profile: {
@@ -67,7 +67,7 @@ export interface CompileTestCase {
6767

6868
export function computeCompileComparisonsWithNonRelevant(
6969
filter: CompileBenchmarkFilter,
70-
data: CompareResponse,
70+
comparisons: [CompileBenchmarkComparison],
7171
benchmarkMap: CompileBenchmarkMap
7272
): TestCaseComparison<CompileTestCase>[] {
7373
function profileFilter(profile: Profile): boolean {
@@ -118,54 +118,29 @@ export function computeCompileComparisonsWithNonRelevant(
118118
);
119119
}
120120

121-
let testCases = data.compile_comparisons
121+
let filteredComparisons = comparisons
122122
.map(
123123
(c: CompileBenchmarkComparison): TestCaseComparison<CompileTestCase> => {
124-
const datumA = c.comparison.statistics[0];
125-
const datumB = c.comparison.statistics[1];
126-
127-
// In the vast majority of cases, we can do the proportional change calculation. However, some
128-
// metrics can be zero. If the initial value is 0, we can't compute the new value as a
129-
// percentage change of the old one. If both values are 0, we can say the change is also 0%.
130-
// If the new value is not 0, the percentage is not really meaningful, but we can say it's 100%.
131-
let percent;
132-
if (datumA === 0) {
133-
if (datumB === 0) {
134-
percent = 0;
135-
} else {
136-
percent = 100;
137-
}
138-
} else {
139-
percent = 100 * ((datumB - datumA) / datumA);
140-
}
141-
142-
return {
143-
testCase: {
144-
benchmark: c.benchmark,
145-
profile: c.profile,
146-
scenario: c.scenario,
147-
category: (benchmarkMap[c.benchmark] || {}).category || "secondary",
148-
},
149-
isRelevant: c.comparison.is_relevant,
150-
significanceFactor: c.comparison.significance_factor,
151-
significanceThreshold: c.comparison.significance_threshold * 100.0, // ensure the threshold is in %
152-
datumA,
153-
datumB,
154-
percent,
124+
let testCase = {
125+
benchmark: c.benchmark,
126+
profile: c.profile,
127+
scenario: c.scenario,
128+
category: (benchmarkMap[c.benchmark] || {}).category || "secondary",
155129
};
130+
return calculateComparison(c.comparison, testCase);
156131
}
157132
)
158133
.filter((tc) => shouldShowTestCase(tc));
159134

160135
// Sort by name first, so that there is a canonical ordering
161136
// of test cases. This ensures the overall order is stable, even if
162137
// individual benchmarks have the same largestChange value.
163-
testCases.sort((a, b) =>
138+
filteredComparisons.sort((a, b) =>
164139
a.testCase.benchmark.localeCompare(b.testCase.benchmark)
165140
);
166-
testCases.sort((a, b) => Math.abs(b.percent) - Math.abs(a.percent));
141+
filteredComparisons.sort((a, b) => Math.abs(b.percent) - Math.abs(a.percent));
167142

168-
return testCases;
143+
return filteredComparisons;
169144
}
170145

171146
export function createCompileBenchmarkMap(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ const benchmarkMap = createCompileBenchmarkMap(props.data);
153153
const allTestCases = computed(() =>
154154
computeCompileComparisonsWithNonRelevant(
155155
filter.value,
156-
props.data,
156+
props.data.compile_comparisons,
157157
benchmarkMap
158158
)
159159
);

site/frontend/src/pages/compare/data.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {BenchmarkFilter} from "./types";
1+
import {BenchmarkFilter, StatComparison} from "./types";
22

33
export interface Summary {
44
count: number;
@@ -23,6 +23,39 @@ export interface TestCaseComparison<Case> {
2323
percent: number;
2424
}
2525

26+
export function calculateComparison<Case>(
27+
comparison: StatComparison,
28+
testCase: Case
29+
): TestCaseComparison<Case> {
30+
const datumA = comparison.statistics[0];
31+
const datumB = comparison.statistics[1];
32+
33+
// In the vast majority of cases, we can do the proportional change calculation. However, some
34+
// metrics can be zero. If the initial value is 0, we can't compute the new value as a
35+
// percentage change of the old one. If both values are 0, we can say the change is also 0%.
36+
// If the new value is not 0, the percentage is not really meaningful, but we can say it's 100%.
37+
let percent;
38+
if (datumA === 0) {
39+
if (datumB === 0) {
40+
percent = 0;
41+
} else {
42+
percent = 100;
43+
}
44+
} else {
45+
percent = 100 * ((datumB - datumA) / datumA);
46+
}
47+
48+
return {
49+
testCase,
50+
isRelevant: comparison.is_relevant,
51+
significanceFactor: comparison.significance_factor,
52+
significanceThreshold: comparison.significance_threshold * 100.0, // ensure the threshold is in %
53+
datumA,
54+
datumB,
55+
percent,
56+
};
57+
}
58+
2659
export function filterNonRelevant<Case>(
2760
filter: BenchmarkFilter,
2861
cases: TestCaseComparison<Case>[]

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import {
2424
defaultCompileFilter as defaultCompileFilter,
2525
} from "./compile/common";
2626
import RuntimeBenchmarksPage from "./runtime/page.vue";
27+
import {
28+
computeRuntimeComparisonsWithNonRelevant,
29+
defaultRuntimeFilter,
30+
} from "./runtime/common";
2731
2832
function loadSelectorFromUrl(urlParams: Dict<string>): CompareSelector {
2933
const start = urlParams["start"] ?? "";
@@ -70,11 +74,20 @@ async function loadCompareData(
7074
defaultCompileFilter,
7175
computeCompileComparisonsWithNonRelevant(
7276
defaultCompileFilter,
73-
response,
77+
response.compile_comparisons,
7478
createCompileBenchmarkMap(response)
7579
)
7680
)
7781
);
82+
runtimeSummary.value = computeSummary(
83+
filterNonRelevant(
84+
defaultRuntimeFilter,
85+
computeRuntimeComparisonsWithNonRelevant(
86+
defaultRuntimeFilter,
87+
response.runtime_comparisons
88+
)
89+
)
90+
);
7891
runtimeDataAvailable.value = response.runtime_comparisons.length > 0;
7992
}
8093
@@ -90,10 +103,11 @@ function updateSelection(params: SelectionParams) {
90103
91104
const urlParams = getUrlParams();
92105
93-
// Include all relevant changes in the compile-time tab summary.
94-
// We do not wrap it in computed, because it should be loaded only once, after
95-
// the data is downloaded.
106+
// Include all relevant changes in the compile-time and runtime tab summaries.
107+
// We do not wrap these summaries in `computed`, because they should be loaded
108+
// only once, after the compare data is downloaded.
96109
const compileSummary: Ref<SummaryGroup | null> = ref(null);
110+
const runtimeSummary: Ref<SummaryGroup | null> = ref(null);
97111
98112
const loading = ref(false);
99113
@@ -139,13 +153,14 @@ loadCompareData(selector, loading);
139153
:data="data"
140154
:initial-tab="initialTab"
141155
:compile-time-summary="compileSummary"
156+
:runtime-summary="runtimeSummary"
142157
/>
143158
<template v-if="activeTab === Tab.CompileTime">
144159
<CompileBenchmarksPage :data="data" :selector="selector" />
145160
</template>
146161
<BootstrapTable v-if="activeTab === Tab.Bootstrap" :data="data" />
147162
<template v-if="runtimeDataAvailable && activeTab === Tab.Runtime">
148-
Runtime data
163+
<RuntimeBenchmarksPage :data="data" />
149164
</template>
150165
</div>
151166
</div>

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import {BenchmarkFilter, StatComparison} from "../types";
1+
import {BenchmarkFilter, CompareResponse, StatComparison} from "../types";
2+
import {calculateComparison, computeSummary, TestCaseComparison} from "../data";
3+
4+
export interface RuntimeTestCase {
5+
benchmark: string;
6+
}
27

38
export type RuntimeBenchmarkFilter = BenchmarkFilter;
49

@@ -12,3 +17,35 @@ export interface RuntimeBenchmarkComparison {
1217
benchmark: string;
1318
comparison: StatComparison;
1419
}
20+
21+
export function computeRuntimeComparisonsWithNonRelevant(
22+
filter: RuntimeBenchmarkFilter,
23+
comparisons: [RuntimeBenchmarkComparison]
24+
): TestCaseComparison<RuntimeTestCase>[] {
25+
function shouldShowTestCase(comparison: TestCaseComparison<RuntimeTestCase>) {
26+
const name = comparison.testCase.benchmark;
27+
const nameFilter = filter.name && filter.name.trim();
28+
return !nameFilter || name.includes(nameFilter);
29+
}
30+
31+
let filteredComparisons = comparisons
32+
.map(
33+
(c: RuntimeBenchmarkComparison): TestCaseComparison<RuntimeTestCase> => {
34+
let testCase = {
35+
benchmark: c.benchmark,
36+
};
37+
return calculateComparison(c.comparison, testCase);
38+
}
39+
)
40+
.filter((tc) => shouldShowTestCase(tc));
41+
42+
// Sort by name first, so that there is a canonical ordering
43+
// of test cases. This ensures the overall order is stable, even if
44+
// individual benchmarks have the same largestChange value.
45+
filteredComparisons.sort((a, b) =>
46+
a.testCase.benchmark.localeCompare(b.testCase.benchmark)
47+
);
48+
filteredComparisons.sort((a, b) => Math.abs(b.percent) - Math.abs(a.percent));
49+
50+
return filteredComparisons;
51+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script setup lang="ts">
2+
import {CompareResponse} from "../types";
3+
4+
const props = defineProps<{data: CompareResponse}>();
5+
</script>
6+
7+
<template></template>

site/frontend/src/pages/compare/tabs.vue

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
<script setup lang="ts">
2-
import {Ref, ref} from "vue";
1+
<script setup lang="tsx">
2+
import {h, ref, Ref} from "vue";
33
import {CompareResponse, Tab} from "./types";
44
import {diffClass, percentClass} from "./shared";
55
import {SummaryGroup} from "./data";
@@ -10,6 +10,7 @@ const props = withDefaults(
1010
defineProps<{
1111
data: CompareResponse;
1212
compileTimeSummary: SummaryGroup;
13+
runtimeSummary: SummaryGroup;
1314
initialTab?: Tab;
1415
}>(),
1516
{
@@ -32,10 +33,39 @@ function formatBootstrap(value: number): string {
3233
return "???";
3334
}
3435
36+
function SummaryTable({summary}: {summary: SummaryGroup}) {
37+
const valid = summary.all.count > 0;
38+
if (valid) {
39+
return (
40+
<table>
41+
<thead>
42+
<tr>
43+
<th>Range</th>
44+
<th>Mean</th>
45+
</tr>
46+
</thead>
47+
<thead>
48+
<tr>
49+
<td>
50+
<SummaryRange range={summary.all.range} />
51+
</td>
52+
<td>
53+
<SummaryPercentValue
54+
className={percentClass(summary.all.average)}
55+
value={summary.all.average}
56+
/>
57+
</td>
58+
</tr>
59+
</thead>
60+
</table>
61+
);
62+
}
63+
return <div>No relevant results</div>;
64+
}
65+
3566
const bootstrapA = props.data.a.bootstrap_total;
3667
const bootstrapB = props.data.b.bootstrap_total;
3768
const bootstrapValid = bootstrapA > 0.0 && bootstrapB > 0.0;
38-
const compileTimeValid = props.compileTimeSummary.all.count > 0;
3969
4070
const activeTab: Ref<Tab> = ref(props.initialTab);
4171
</script>
@@ -49,31 +79,8 @@ const activeTab: Ref<Tab> = ref(props.initialTab);
4979
@click="changeTab(Tab.CompileTime)"
5080
>
5181
<div class="title">Compile-time</div>
52-
<div class="summary compile-time">
53-
<template v-if="compileTimeValid">
54-
<table>
55-
<thead>
56-
<tr>
57-
<th>Range</th>
58-
<th>Mean</th>
59-
</tr>
60-
</thead>
61-
<thead>
62-
<tr>
63-
<td>
64-
<SummaryRange :range="compileTimeSummary.all.range" />
65-
</td>
66-
<td>
67-
<SummaryPercentValue
68-
:class="percentClass(compileTimeSummary.all.average)"
69-
:value="compileTimeSummary.all.average"
70-
/>
71-
</td>
72-
</tr>
73-
</thead>
74-
</table>
75-
</template>
76-
<template v-else>No relevant results</template>
82+
<div class="summary table-wrapper">
83+
<SummaryTable :summary="compileTimeSummary" />
7784
</div>
7885
</div>
7986
<div
@@ -83,7 +90,9 @@ const activeTab: Ref<Tab> = ref(props.initialTab);
8390
@click="changeTab(Tab.Runtime)"
8491
>
8592
<div class="title">Runtime</div>
86-
<div class="summary runtime"></div>
93+
<div class="summary table-wrapper">
94+
<SummaryTable :summary="runtimeSummary" />
95+
</div>
8796
</div>
8897
<div
8998
class="tab"
@@ -144,6 +153,7 @@ const activeTab: Ref<Tab> = ref(props.initialTab);
144153
&:not(:first-child) {
145154
margin-left: 30px;
146155
}
156+
147157
&:not(:last-child) {
148158
:after {
149159
content: "";
@@ -168,7 +178,7 @@ const activeTab: Ref<Tab> = ref(props.initialTab);
168178
border-color: black;
169179
}
170180
171-
.compile-time {
181+
.table-wrapper {
172182
table {
173183
width: 100%;
174184
table-layout: auto;

0 commit comments

Comments
 (0)