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

Commit ea914eb

Browse files
authored
Merge pull request rust-lang#1650 from Kobzol/runtime-ui-ext
Add filters to runtime comparison tab
2 parents 8625ca4 + 55949c3 commit ea914eb

File tree

12 files changed

+317
-41
lines changed

12 files changed

+317
-41
lines changed

database/src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ impl Index {
594594
// millions of queries and labels and iterating all of them is eventually
595595
// going to be impractical. But for now it performs quite well, so we'll go
596596
// for it as keeping indices around would be annoying.
597-
pub fn metrics(&self) -> Vec<String> {
597+
pub fn compile_metrics(&self) -> Vec<String> {
598598
self.pstat_series
599599
.map
600600
.keys()
@@ -605,6 +605,17 @@ impl Index {
605605
.collect()
606606
}
607607

608+
pub fn runtime_metrics(&self) -> Vec<String> {
609+
self.runtime_pstat_series
610+
.map
611+
.keys()
612+
.map(|(_, metric)| metric)
613+
.collect::<std::collections::HashSet<_>>()
614+
.into_iter()
615+
.map(|s| s.to_string())
616+
.collect()
617+
}
618+
608619
// FIXME: in theory this won't scale indefinitely as there's potentially
609620
// millions of queries and labels and iterating all of them is eventually
610621
// going to be impractical. But for now it performs quite well, so we'll go

site/frontend/src/api.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import {getJson} from "./utils/requests";
22
import {INFO_URL} from "./urls";
33

44
export interface BenchmarkInfo {
5-
// Known statistic values from the DB
6-
stats: [string];
5+
// Known compile metrics from the DB
6+
compile_metrics: [string];
7+
// Known runtime metrics from the DB
8+
runtime_metrics: [string];
79
// Last loaded run date
810
as_of: string | null;
911
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type CompileBenchmarkFilter = {
2323
library: boolean;
2424
};
2525
} & BenchmarkFilter;
26+
2627
export const defaultCompileFilter: CompileBenchmarkFilter = {
2728
name: null,
2829
nonRelevant: false,

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

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from "./common";
1818
import {BenchmarkInfo} from "../../../api";
1919
import {importantCompileMetrics} from "../metrics";
20+
import {getBoolOrDefault} from "../shared";
2021
2122
const props = defineProps<{
2223
data: CompareResponse;
@@ -28,45 +29,65 @@ function loadFilterFromUrl(
2829
urlParams: Dict<string>,
2930
defaultFilter: CompileBenchmarkFilter
3031
): CompileBenchmarkFilter {
31-
function getBoolOrDefault(name: string, defaultValue: boolean): boolean {
32-
if (urlParams.hasOwnProperty(name)) {
33-
return urlParams[name] === "true";
34-
}
35-
return defaultValue;
36-
}
37-
3832
return {
3933
name: urlParams["name"] ?? defaultFilter.name,
40-
nonRelevant: getBoolOrDefault("nonRelevant", defaultFilter.nonRelevant),
41-
showRawData: getBoolOrDefault("showRawData", defaultFilter.showRawData),
34+
nonRelevant: getBoolOrDefault(
35+
urlParams,
36+
"nonRelevant",
37+
defaultFilter.nonRelevant
38+
),
39+
showRawData: getBoolOrDefault(
40+
urlParams,
41+
"showRawData",
42+
defaultFilter.showRawData
43+
),
4244
profile: {
43-
check: getBoolOrDefault("check", defaultFilter.profile.check),
44-
debug: getBoolOrDefault("debug", defaultFilter.profile.debug),
45-
opt: getBoolOrDefault("opt", defaultFilter.profile.opt),
46-
doc: getBoolOrDefault("doc", defaultFilter.profile.doc),
45+
check: getBoolOrDefault(urlParams, "check", defaultFilter.profile.check),
46+
debug: getBoolOrDefault(urlParams, "debug", defaultFilter.profile.debug),
47+
opt: getBoolOrDefault(urlParams, "opt", defaultFilter.profile.opt),
48+
doc: getBoolOrDefault(urlParams, "doc", defaultFilter.profile.doc),
4749
},
4850
scenario: {
49-
full: getBoolOrDefault("full", defaultFilter.scenario.full),
50-
incrFull: getBoolOrDefault("incrFull", defaultFilter.scenario.incrFull),
51+
full: getBoolOrDefault(urlParams, "full", defaultFilter.scenario.full),
52+
incrFull: getBoolOrDefault(
53+
urlParams,
54+
"incrFull",
55+
defaultFilter.scenario.incrFull
56+
),
5157
incrUnchanged: getBoolOrDefault(
58+
urlParams,
5259
"incrUnchanged",
5360
defaultFilter.scenario.incrUnchanged
5461
),
5562
incrPatched: getBoolOrDefault(
63+
urlParams,
5664
"incrPatched",
5765
defaultFilter.scenario.incrPatched
5866
),
5967
},
6068
category: {
61-
primary: getBoolOrDefault("primary", defaultFilter.category.primary),
69+
primary: getBoolOrDefault(
70+
urlParams,
71+
"primary",
72+
defaultFilter.category.primary
73+
),
6274
secondary: getBoolOrDefault(
75+
urlParams,
6376
"secondary",
6477
defaultFilter.category.secondary
6578
),
6679
},
6780
artifact: {
68-
binary: getBoolOrDefault("binary", defaultFilter.artifact.binary),
69-
library: getBoolOrDefault("library", defaultFilter.artifact.library),
81+
binary: getBoolOrDefault(
82+
urlParams,
83+
"binary",
84+
defaultFilter.artifact.binary
85+
),
86+
library: getBoolOrDefault(
87+
urlParams,
88+
"library",
89+
defaultFilter.artifact.library
90+
),
7091
},
7192
};
7293
}
@@ -140,6 +161,17 @@ function storeFilterToUrl(
140161
function updateFilter(newFilter: CompileBenchmarkFilter) {
141162
storeFilterToUrl(newFilter, defaultCompileFilter, getUrlParams());
142163
filter.value = newFilter;
164+
refreshQuickLinks();
165+
}
166+
167+
/**
168+
* When the filter changes, the URL is updated.
169+
* After that happens, we want to re-render the quick links component, because
170+
* it contains links that are "relative" to the current URL. Changing this
171+
* key ref will cause it to be re-rendered.
172+
*/
173+
function refreshQuickLinks() {
174+
quickLinksKey.value += 1;
143175
}
144176
145177
function exportData() {
@@ -148,6 +180,7 @@ function exportData() {
148180
149181
const urlParams = getUrlParams();
150182
183+
const quickLinksKey = ref(0);
151184
const filter = ref(loadFilterFromUrl(urlParams, defaultCompileFilter));
152185
153186
const benchmarkMap = createCompileBenchmarkMap(props.data);
@@ -166,9 +199,10 @@ const filteredSummary = computed(() => computeSummary(comparisons.value));
166199

167200
<template>
168201
<MetricSelector
202+
:key="quickLinksKey"
169203
:quick-links="importantCompileMetrics"
170204
:selected-metric="selector.stat"
171-
:benchmark-info="benchmarkInfo"
205+
:metrics="benchmarkInfo.compile_metrics"
172206
/>
173207
<Filters
174208
:defaultFilter="defaultCompileFilter"

site/frontend/src/pages/compare/header/data-selector.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ const opened = ref(false);
7979
"
8080
>
8181
<select class="stats" ref="statRef">
82-
<option v-for="value in props.info.stats" :value="value">
82+
<option
83+
v-for="value in props.info.compile_metrics"
84+
:value="value"
85+
>
8386
{{ value }}
8487
</option>
8588
</select>

site/frontend/src/pages/compare/metric-selector.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@ import {MetricDescription} from "./metrics";
99
const props = defineProps<{
1010
quickLinks: MetricDescription[];
1111
selectedMetric: string;
12-
benchmarkInfo: BenchmarkInfo;
12+
metrics: string[];
1313
}>();
1414
15-
function navigateToMetric(metric: string) {
15+
function createUrlForMetric(metric: string): URL {
1616
const params = {stat: metric};
17-
const url = createUrlWithAppendedParams(params);
18-
navigateToUrlParams(url.searchParams);
17+
return createUrlWithAppendedParams(params);
1918
}
2019
2120
function changeMetric(e: Event) {
2221
const target = e.target as HTMLSelectElement;
2322
const metric = target.value;
24-
navigateToMetric(metric);
23+
navigateToUrlParams(createUrlForMetric(metric).searchParams);
2524
}
2625
</script>
2726

@@ -33,13 +32,13 @@ function changeMetric(e: Event) {
3332
:class="{active: props.selectedMetric === metric.metric}"
3433
:title="metric.description"
3534
>
36-
<a href="#" @click.prevent="() => navigateToMetric(metric.metric)">{{
35+
<a :href="createUrlForMetric(metric.metric).toString()">{{
3736
metric.label
3837
}}</a>
3938
</div>
40-
<select class="stats" @change="changeMetric">
39+
<select class="stats" @change="changeMetric" v-if="metrics.length > 0">
4140
<option
42-
v-for="value in benchmarkInfo.stats"
41+
v-for="value in metrics"
4342
:value="value"
4443
:selected="value === selectedMetric"
4544
>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<script setup lang="ts">
2+
import Toggle from "../toggle.vue";
3+
import Tooltip from "../tooltip.vue";
4+
import {ref, toRaw, watch} from "vue";
5+
import {deepCopy} from "../../../utils/copy";
6+
import {PREF_FILTERS_OPENED} from "../prefs";
7+
import {createPersistedRef} from "../../../storage";
8+
import {RuntimeBenchmarkFilter} from "./common";
9+
10+
const props = defineProps<{
11+
// When reset, set filter to this value
12+
defaultFilter: RuntimeBenchmarkFilter;
13+
// Initialize the filter with this value
14+
initialFilter: RuntimeBenchmarkFilter;
15+
}>();
16+
const emit = defineEmits<{
17+
(e: "change", filter: RuntimeBenchmarkFilter): void;
18+
(e: "export"): void;
19+
}>();
20+
21+
function reset() {
22+
// We must not change the default filter
23+
filter.value = deepCopy(props.defaultFilter);
24+
}
25+
26+
let filter = ref(deepCopy(props.initialFilter));
27+
watch(
28+
filter,
29+
(newValue, _) => {
30+
emit("change", toRaw(newValue));
31+
},
32+
{deep: true}
33+
);
34+
35+
const opened = createPersistedRef(PREF_FILTERS_OPENED);
36+
</script>
37+
38+
<template>
39+
<fieldset class="collapsible-section">
40+
<Toggle :opened="opened" @change="(value) => (opened = value)">
41+
<template #label>Filters</template>
42+
<template #content>
43+
<div>
44+
<div class="section">
45+
<div class="section-heading">Filter</div>
46+
<input id="filter" type="text" v-model="filter.name" />
47+
</div>
48+
<div class="section">
49+
<div class="section-heading">
50+
<span>Show non-relevant results</span>
51+
<Tooltip>
52+
Whether to show test case results that are not relevant (i.e.,
53+
not significant or have a large enough magnitude). You can see
54+
<a
55+
href="https://github.com/rust-lang/rustc-perf/blob/master/docs/comparison-analysis.md#how-is-relevance-of-a-test-run-summary-determined"
56+
>
57+
here</a
58+
>
59+
how relevance is calculated.
60+
</Tooltip>
61+
</div>
62+
<input
63+
type="checkbox"
64+
v-model="filter.nonRelevant"
65+
style="margin-left: 20px"
66+
/>
67+
</div>
68+
<div class="section">
69+
<div class="section-heading">
70+
<span>Display raw data</span>
71+
<Tooltip>Whether to display or not raw data columns.</Tooltip>
72+
</div>
73+
<input
74+
type="checkbox"
75+
v-model="filter.showRawData"
76+
style="margin-left: 20px"
77+
/>
78+
</div>
79+
<button @click="reset" style="margin-right: 10px">
80+
Reset filters
81+
</button>
82+
</div>
83+
</template>
84+
</Toggle>
85+
</fieldset>
86+
</template>
87+
88+
<style scoped lang="scss">
89+
.section-heading {
90+
font-size: 16px;
91+
}
92+
93+
#filter {
94+
margin-left: 52px;
95+
}
96+
97+
.states-list {
98+
display: flex;
99+
flex-direction: column;
100+
align-items: start;
101+
list-style: none;
102+
margin: 0;
103+
padding: 0;
104+
}
105+
106+
.section-list-wrapper {
107+
flex-direction: column;
108+
}
109+
110+
@media (min-width: 760px) {
111+
.states-list {
112+
justify-content: start;
113+
flex-direction: row;
114+
align-items: center;
115+
width: 80%;
116+
}
117+
118+
.section-list-wrapper {
119+
flex-direction: row;
120+
}
121+
}
122+
123+
.states-list > li {
124+
margin-right: 15px;
125+
}
126+
127+
.cache-label {
128+
font-weight: bold;
129+
}
130+
</style>

0 commit comments

Comments
 (0)