Skip to content

Commit 85985de

Browse files
committed
Add summary tabs on compare page
1 parent 67b966f commit 85985de

File tree

5 files changed

+253
-28
lines changed

5 files changed

+253
-28
lines changed

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import {CompareResponse} from "./types";
3-
import {percentClass} from "./shared";
3+
import {diffClass, percentClass} from "./shared";
44
55
const props = defineProps<{data: CompareResponse}>();
66
@@ -44,16 +44,6 @@ const bootstraps = Object.entries(props.data.a.bootstrap)
4444
return a.name.localeCompare(b.name);
4545
}
4646
});
47-
48-
function diffClass(diff: number): string {
49-
let klass = "";
50-
if (diff > 1) {
51-
klass = "positive";
52-
} else if (diff < -1) {
53-
klass = "negative";
54-
}
55-
return klass;
56-
}
5747
</script>
5848

5949
<template>

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

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {computed, Ref, ref} from "vue";
1111
import {withLoading} from "../../utils/loading";
1212
import {postMsgpack} from "../../utils/requests";
1313
import {COMPARE_DATA_URL} from "../../urls";
14-
import {CompareResponse, CompareSelector, DataFilter} from "./types";
14+
import {CompareResponse, CompareSelector, DataFilter, Tab} from "./types";
1515
import BootstrapTable from "./bootstrap-table.vue";
1616
import Header from "./header/header.vue";
1717
import DataSelector, {SelectionParams} from "./header/data-selector.vue";
@@ -23,10 +23,12 @@ import {
2323
computeSummary,
2424
computeTestCasesWithNonRelevant,
2525
filterNonRelevant,
26+
SummaryGroup,
2627
} from "./data";
2728
import OverallTable from "./summary/overall-table.vue";
2829
import Aggregations from "./summary/aggregations.vue";
2930
import Benchmarks from "./benchmarks/benchmarks.vue";
31+
import Tabs from "./tabs.vue";
3032
3133
function loadSelectorFromUrl(urlParams: Dict<string>): CompareSelector {
3234
const start = urlParams["start"] ?? "";
@@ -158,6 +160,16 @@ async function loadCompareData(
158160
return await postMsgpack<CompareResponse>(COMPARE_DATA_URL, params);
159161
});
160162
data.value = response;
163+
totalSummary.value = computeSummary(
164+
filterNonRelevant(
165+
defaultFilter,
166+
computeTestCasesWithNonRelevant(
167+
defaultFilter,
168+
data.value,
169+
benchmarkMap.value
170+
)
171+
)
172+
);
161173
}
162174
163175
function updateSelection(params: SelectionParams) {
@@ -222,13 +234,24 @@ const testCases = computed(() =>
222234
);
223235
const filteredSummary = computed(() => computeSummary(testCases.value));
224236
237+
// Include all relevant changes in the compile-time tab summary
238+
// We do not wrap it in computed, because it should be loaded only once, after
239+
// the data is downloaded.
240+
const totalSummary: Ref<SummaryGroup | null> = ref(null);
241+
225242
const loading = ref(false);
226243
227244
const quickLinksKey = ref(0);
228245
const info = await loadBenchmarkInfo();
229246
const selector = loadSelectorFromUrl(urlParams);
230247
const filter = ref(loadFilterFromUrl(urlParams, defaultFilter));
231248
249+
const tab: Ref<Tab> = ref(Tab.CompileTime);
250+
251+
function changeTab(newTab: Tab) {
252+
tab.value = newTab;
253+
}
254+
232255
const data: Ref<CompareResponse | null> = ref(null);
233256
loadCompareData(selector, loading);
234257
</script>
@@ -247,23 +270,30 @@ loadCompareData(selector, loading);
247270
<p>Loading ...</p>
248271
</div>
249272
<div v-if="data !== null">
250-
<QuickLinks :stat="selector.stat" :key="quickLinksKey" />
251-
<Filters
252-
:defaultFilter="defaultFilter"
253-
:initialFilter="filter"
254-
@change="updateFilter"
255-
@export="exportData"
256-
/>
257-
<OverallTable :summary="filteredSummary" />
258-
<Aggregations :cases="testCases" />
259-
<Benchmarks
273+
<Tabs
274+
@change-tab="changeTab"
260275
:data="data"
261-
:test-cases="testCases"
262-
:all-test-cases="allTestCases"
263-
:filter="filter"
264-
:stat="selector.stat"
265-
></Benchmarks>
266-
<BootstrapTable :data="data" />
276+
:compile-time-summary="totalSummary"
277+
/>
278+
<template v-if="tab === Tab.CompileTime">
279+
<QuickLinks :stat="selector.stat" :key="quickLinksKey" />
280+
<Filters
281+
:defaultFilter="defaultFilter"
282+
:initialFilter="filter"
283+
@change="updateFilter"
284+
@export="exportData"
285+
/>
286+
<OverallTable :summary="filteredSummary" />
287+
<Aggregations :cases="testCases" />
288+
<Benchmarks
289+
:data="data"
290+
:test-cases="testCases"
291+
:all-test-cases="allTestCases"
292+
:filter="filter"
293+
:stat="selector.stat"
294+
></Benchmarks>
295+
</template>
296+
<BootstrapTable v-if="tab === Tab.Bootstrap" :data="data" />
267297
</div>
268298
</div>
269299
<br />

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,13 @@ export function percentClass(pct: number): string {
2727
}
2828
return klass;
2929
}
30+
31+
export function diffClass(diff: number): string {
32+
let klass = "";
33+
if (diff > 1) {
34+
klass = "positive";
35+
} else if (diff < -1) {
36+
klass = "negative";
37+
}
38+
return klass;
39+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<script lang="ts"></script>
2+
3+
<script setup lang="ts">
4+
import {Ref, ref} from "vue";
5+
import {CompareResponse, Tab} from "./types";
6+
import {diffClass, percentClass} from "./shared";
7+
import {SummaryGroup} from "./data";
8+
import SummaryPercentValue from "./summary/percent-value.vue";
9+
10+
const props = withDefaults(
11+
defineProps<{
12+
data: CompareResponse;
13+
compileTimeSummary: SummaryGroup;
14+
initialTab?: Tab;
15+
}>(),
16+
{
17+
initialTab: Tab.CompileTime,
18+
}
19+
);
20+
const emit = defineEmits<{
21+
(e: "changeTab", tab: Tab): void;
22+
}>();
23+
24+
function changeTab(tab: Tab) {
25+
activeTab.value = tab;
26+
emit("changeTab", tab);
27+
}
28+
29+
function formatBootstrap(value: number): string {
30+
if (value > 0.0) {
31+
return (value / 10e8).toFixed(3);
32+
}
33+
return "???";
34+
}
35+
36+
const bootstrapA = props.data.a.bootstrap_total;
37+
const bootstrapB = props.data.b.bootstrap_total;
38+
const bootstrapValid = bootstrapA > 0.0 && bootstrapB > 0.0;
39+
const compileTimeValid = props.compileTimeSummary.all.count > 0;
40+
41+
const activeTab: Ref<Tab> = ref(props.initialTab);
42+
</script>
43+
44+
<template>
45+
<div class="wrapper">
46+
<div
47+
class="tab"
48+
title="Compilation time benchmarks"
49+
:class="{selected: activeTab === Tab.CompileTime}"
50+
@click="changeTab(Tab.CompileTime)"
51+
>
52+
<div class="title">Compile-time</div>
53+
<div class="summary compile-time">
54+
<template v-if="compileTimeValid">
55+
<table>
56+
<thead>
57+
<tr>
58+
<th>min</th>
59+
<th>max</th>
60+
<th>avg</th>
61+
</tr>
62+
</thead>
63+
<thead>
64+
<tr>
65+
<td>
66+
<SummaryPercentValue
67+
:class="percentClass(compileTimeSummary.all.range[0])"
68+
:value="compileTimeSummary.all.range[0]"
69+
/>
70+
</td>
71+
<td>
72+
<SummaryPercentValue
73+
:class="percentClass(compileTimeSummary.all.range[1])"
74+
:value="compileTimeSummary.all.range[1]"
75+
/>
76+
</td>
77+
<td>
78+
<SummaryPercentValue
79+
:class="percentClass(compileTimeSummary.all.average)"
80+
:value="compileTimeSummary.all.average"
81+
/>
82+
</td>
83+
</tr>
84+
</thead>
85+
</table>
86+
</template>
87+
<template v-else>No relevant results</template>
88+
</div>
89+
</div>
90+
<div
91+
class="tab"
92+
title="Bootstrap duration"
93+
:class="{selected: activeTab === Tab.Bootstrap}"
94+
@click="changeTab(Tab.Bootstrap)"
95+
>
96+
<div class="title">Bootstrap</div>
97+
<div
98+
:class="{[diffClass(bootstrapB - bootstrapA)]: bootstrapValid}"
99+
class="summary"
100+
>
101+
<div>
102+
{{ formatBootstrap(bootstrapA) }} ->
103+
{{ formatBootstrap(bootstrapB) }}
104+
</div>
105+
<div v-if="bootstrapValid">
106+
{{ ((bootstrapB - bootstrapA) / 10e8).toFixed(1) }}s ({{
107+
(((bootstrapB - bootstrapA) / bootstrapA) * 100).toFixed(3)
108+
}}%)
109+
</div>
110+
</div>
111+
</div>
112+
</div>
113+
</template>
114+
115+
<style scoped lang="scss">
116+
.wrapper {
117+
display: flex;
118+
flex-direction: column;
119+
align-items: center;
120+
padding: 20px 0;
121+
122+
@media (min-width: 600px) {
123+
justify-content: center;
124+
flex-direction: row;
125+
align-items: normal;
126+
}
127+
}
128+
129+
.tab {
130+
display: flex;
131+
flex-direction: column;
132+
position: relative;
133+
width: 200px;
134+
height: 60px;
135+
padding: 5px;
136+
text-align: center;
137+
border: 2px dotted #cccccc;
138+
border-radius: 5px;
139+
cursor: pointer;
140+
141+
&:hover {
142+
@extend .selected;
143+
}
144+
145+
@media (min-width: 600px) {
146+
&:not(:first-child) {
147+
margin-left: 30px;
148+
}
149+
&:not(:last-child) {
150+
:after {
151+
content: "";
152+
position: absolute;
153+
right: -17px;
154+
border-right: 1px solid black;
155+
top: 20%;
156+
bottom: 20%;
157+
}
158+
}
159+
}
160+
}
161+
162+
.title {
163+
font-weight: bold;
164+
margin-bottom: 4px;
165+
}
166+
167+
.selected {
168+
border-style: solid;
169+
border-color: black;
170+
}
171+
172+
.compile-time {
173+
table {
174+
width: 100%;
175+
table-layout: auto;
176+
}
177+
178+
th {
179+
font-weight: normal;
180+
}
181+
}
182+
183+
.summary {
184+
display: flex;
185+
flex-direction: column;
186+
justify-content: center;
187+
font-size: 0.9em;
188+
flex-grow: 1;
189+
}
190+
</style>

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,8 @@ export interface CompareResponse {
6666
new_errors: Array<[string, string]>;
6767
compile_benchmark_data: [CompileBenchmarkDescription];
6868
}
69+
70+
export enum Tab {
71+
CompileTime,
72+
Bootstrap,
73+
}

0 commit comments

Comments
 (0)