Skip to content

Commit 7b25565

Browse files
committed
Convert detailed-query page to a template
1 parent d904faa commit 7b25565

File tree

7 files changed

+410
-414
lines changed

7 files changed

+410
-414
lines changed

site/src/server.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,11 @@ async fn handle_fs_path(req: &Request, path: &str) -> Option<http::Response<hype
599599
}
600600

601601
let source = match path {
602-
"/bootstrap.html" | "/dashboard.html" | "/help.html" | "/status.html" => TEMPLATES
602+
"/bootstrap.html"
603+
| "/dashboard.html"
604+
| "/detailed-query.html"
605+
| "/help.html"
606+
| "/status.html" => TEMPLATES
603607
.render(&format!("pages/{}", path.trim_start_matches("/")))
604608
.await
605609
.unwrap()

site/static/detailed-query.html

Lines changed: 0 additions & 410 deletions
This file was deleted.

site/static/scripts/detailed-query.js

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
function to_seconds(time) {
2+
return time / 1000000000;
3+
}
4+
5+
function fmt_delta(to, delta, is_integral_delta) {
6+
let from = to - delta;
7+
let pct = (to - from) / from * 100;
8+
if (from == to) {
9+
pct = 0;
10+
}
11+
let classes;
12+
if (pct > 1) {
13+
classes = "positive";
14+
} else if (pct < -1) {
15+
classes = "negative";
16+
} else {
17+
classes = "neutral";
18+
}
19+
// some arbitrary "small" value
20+
// ignore this because it's not too interesting likely
21+
if (Math.abs(delta) <= 0.05) {
22+
classes = "neutral";
23+
}
24+
let text;
25+
if (is_integral_delta) {
26+
text = delta.toString();
27+
} else {
28+
text = delta.toFixed(3);
29+
}
30+
if (pct != Infinity && pct != -Infinity) {
31+
text += `(${pct.toFixed(1)}%)`.padStart(10, ' ');
32+
} else {
33+
text += `-`.padStart(10, ' ');
34+
}
35+
return `<span class="${classes}" title="${from.toFixed(3)} to ${to.toFixed(3)}${delta.toFixed(3)}">${text}</span>`;
36+
}
37+
38+
function populate_data(data, state) {
39+
let txt = `${state.commit.substring(0, 10)}: Self profile results for ${state.benchmark} run ${state.scenario}`;
40+
if (state.base_commit) {
41+
let self_href =
42+
`/detailed-query.html?sort_idx=${state.sort_idx}&commit=${state.commit}&scenario=${state.scenario}&benchmark=${state.benchmark}`;
43+
let base_href =
44+
`/detailed-query.html?sort_idx=${state.sort_idx}&commit=${state.base_commit}&scenario=${state.scenario}&benchmark=${state.benchmark}`;
45+
txt += `<br>diff vs base ${state.base_commit.substring(0, 10)}, <a href="${base_href}">query info for just base commit</a>`;
46+
txt += `<br><a href="${self_href}">query info for just this commit</a>`;
47+
}
48+
document.querySelector("#title").innerHTML = txt;
49+
let dl_url = (commit, bench, run) => {
50+
return `/perf/download-raw-self-profile?commit=${commit}&benchmark=${bench}&scenario=${run}`
51+
};
52+
let dl_link = (commit, bench, run) => {
53+
let url = dl_url(commit, bench, run);
54+
return `<a href="${url}">raw</a>`;
55+
};
56+
let processed_url = (commit, bench, run, ty) => {
57+
return `/perf/processed-self-profile?commit=${commit}&benchmark=${bench}&scenario=${run}&type=${ty}`;
58+
};
59+
let processed_link = (commit, {benchmark, scenario}, ty) => {
60+
let url = processed_url(commit, benchmark, scenario, ty);
61+
return `<a href="${url}">${ty}</a>`;
62+
};
63+
let processed_crox_url = (commit, bench, run) => {
64+
let crox_url = window.location.origin + processed_url(commit, bench, run, "crox");
65+
return encodeURIComponent(crox_url);
66+
};
67+
let speedscope_link = (commit, bench, run) => {
68+
let benchmark_name = `${bench} run ${run}`;
69+
let crox_url = processed_crox_url(commit, bench, run);
70+
let speedscope_url = `https://www.speedscope.app/#profileURL=${crox_url}&title=${encodeURIComponent(benchmark_name)}`;
71+
return `<a href="${speedscope_url}">speedscope.app</a>`;
72+
};
73+
let firefox_profiler_link = (commit, bench, run) => {
74+
let crox_url = processed_crox_url(commit, bench, run);
75+
let ff_url = `https://profiler.firefox.com/from-url/${crox_url}/marker-chart/?v=5`;
76+
return `<a href="${ff_url}">Firefox profiler</a>`;
77+
};
78+
txt = "";
79+
if (state.base_commit) {
80+
txt += `Download/view
81+
${dl_link(state.base_commit, state.benchmark, state.scenario)},
82+
${processed_link(state.base_commit, state, "flamegraph")},
83+
${processed_link(state.base_commit, state, "crox")},
84+
${processed_link(state.base_commit, state, "codegen-schedule")}
85+
(${speedscope_link(state.base_commit, state.benchmark, state.scenario)},
86+
${firefox_profiler_link(state.base_commit, state.benchmark, state.scenario)})
87+
results for ${state.base_commit.substring(0, 10)} (base commit)`;
88+
txt += "<br>";
89+
}
90+
txt += `Download/view
91+
${dl_link(state.commit, state.benchmark, state.scenario)},
92+
${processed_link(state.commit, state, "flamegraph")},
93+
${processed_link(state.commit, state, "crox")},
94+
${processed_link(state.commit, state, "codegen-schedule")}
95+
(${speedscope_link(state.commit, state.benchmark, state.scenario)},
96+
${firefox_profiler_link(state.commit, state.benchmark, state.scenario)})
97+
results for ${state.commit.substring(0, 10)} (new commit)`;
98+
let profile = b => b.endsWith("-opt") ? "Opt" :
99+
b.endsWith("-doc") ? "Doc" :
100+
b.endsWith("-debug") ? "Debug" :
101+
b.endsWith("-check") ? "Check" : "???";
102+
let bench_name = b => b.replace(/-[^-]*$/, "");
103+
let scenario_filter = s => s == "full" ? "Full" :
104+
s == "incr-full" ? "IncrFull" :
105+
s == "incr-unchanged" ? "IncrUnchanged" :
106+
s.startsWith("incr-patched") ? "IncrPatched" :
107+
"???";
108+
if (state.base_commit) {
109+
txt += "<br>";
110+
txt += `Diff: <a
111+
href="/perf/processed-self-profile?commit=${state.commit}&base_commit=${state.base_commit}&benchmark=${state.benchmark}&scenario=${state.scenario}&type=codegen-schedule"
112+
>codegen-schedule</a>`;
113+
txt += "<br>Local profile (base): <code>" +
114+
`./target/release/collector profile_local cachegrind
115+
+${state.base_commit} --include ${bench_name(state.benchmark)} --profiles
116+
${profile(state.benchmark)} --scenarios ${scenario_filter(state.scenario)}</code>`;
117+
}
118+
txt += "<br>Local profile (new): <code>" +
119+
`./target/release/collector profile_local cachegrind
120+
+${state.commit} --include ${bench_name(state.benchmark)} --profiles
121+
${profile(state.benchmark)} --scenarios ${scenario_filter(state.scenario)}</code>`;
122+
if (state.base_commit) {
123+
txt += "<br>Local profile (diff): <code>" +
124+
`./target/release/collector profile_local cachegrind
125+
+${state.base_commit} --rustc2 +${state.commit} --include ${bench_name(state.benchmark)} --profiles
126+
${profile(state.benchmark)} --scenarios ${scenario_filter(state.scenario)}</code>`;
127+
}
128+
document.querySelector("#raw-urls").innerHTML = txt;
129+
let sort_idx = state.sort_idx;
130+
if (!data.base_profile_delta) {
131+
document.body.classList.add("hide-delta");
132+
}
133+
let header = document.getElementById("table-header");
134+
for (let th of header.querySelectorAll("th")) {
135+
// Skip non-sortable columns
136+
if (!th.attributes["data-sort-idx"]) {
137+
continue;
138+
}
139+
let idx = th.attributes["data-sort-idx"].value;
140+
if (idx == sort_idx) {
141+
th.setAttribute("data-sorted-by", "desc");
142+
} else if (idx == -sort_idx) {
143+
th.setAttribute("data-sorted-by", "asc");
144+
}
145+
let sortedBy = th.attributes["data-sorted-by"];
146+
let clickState = Object.assign({}, state);
147+
if (sortedBy && sortedBy.value == "desc") {
148+
clickState.sort_idx = -idx;
149+
} else if (sortedBy && sortedBy.value == "asc") {
150+
clickState.sort_idx = idx;
151+
} else {
152+
// start with descending
153+
if (th.attributes["data-default-sort-dir"].value == "1") {
154+
clickState.sort_idx = idx;
155+
} else {
156+
clickState.sort_idx = -idx;
157+
}
158+
}
159+
let inner = th.innerHTML;
160+
th.innerHTML = `<a href="${query_string_for_state(clickState)}">${inner}</a>`;
161+
}
162+
163+
if (!state.scenario.includes("incr-")) {
164+
// No need to show incremental columns if not showing
165+
// incremental data.
166+
document.body.classList.add("hide-incr");
167+
}
168+
169+
let table = document.getElementById("primary-table");
170+
let idx = 0;
171+
for (let element of [data.profile.totals, ...data.profile.query_data]) {
172+
let cur = to_object(element);
173+
let delta = null;
174+
if (data.base_profile_delta) {
175+
if (idx == 0) {
176+
delta = data.base_profile_delta.totals;
177+
} else {
178+
delta = data.base_profile_delta.query_data[idx - 1];
179+
}
180+
}
181+
let row = document.createElement("tr");
182+
183+
function td(row, content, is_delta) {
184+
let td = document.createElement("td");
185+
td.innerHTML = content;
186+
if (is_delta) {
187+
td.classList.add("delta");
188+
}
189+
row.appendChild(td);
190+
return td;
191+
}
192+
193+
td(row, cur.label);
194+
if (cur.percent_total_time < 0) {
195+
td(row, "-").setAttribute("title", "No wall-time stat collected for this run");
196+
} else {
197+
let t = td(row, cur.percent_total_time.toFixed(2) + "%");
198+
if (idx == 0) {
199+
t.innerText += "*";
200+
t.setAttribute("title", "% of cpu-time stat");
201+
}
202+
}
203+
td(row, to_seconds(cur.self_time).toFixed(3));
204+
if (delta) {
205+
td(row, fmt_delta(to_seconds(cur.self_time), to_seconds(delta.self_time), false), true);
206+
} else {
207+
td(row, "-", true);
208+
}
209+
td(row, cur.invocation_count);
210+
if (delta) {
211+
td(row, fmt_delta(cur.invocation_count, delta.invocation_count, true), true);
212+
} else {
213+
td(row, "-", true);
214+
}
215+
td(row,
216+
to_seconds(cur.incremental_load_time).toFixed(3)).classList.add("incr");
217+
if (delta) {
218+
td(row,
219+
fmt_delta(
220+
to_seconds(cur.incremental_load_time),
221+
to_seconds(delta.incremental_load_time),
222+
false,
223+
),
224+
true).classList.add("incr");
225+
} else {
226+
td(row, "-", true).classList.add("incr");
227+
}
228+
table.appendChild(row);
229+
idx += 1;
230+
}
231+
232+
let artifactTable = document.getElementById("artifact-body");
233+
234+
function td(row, content) {
235+
let td = document.createElement("td");
236+
td.innerHTML = content;
237+
row.appendChild(td);
238+
return td;
239+
}
240+
241+
for (let [idx, element] of data.profile.artifact_sizes.entries()) {
242+
let row = document.createElement("tr");
243+
const label = td(row, element.label);
244+
label.style.textAlign = "center";
245+
td(row, element.bytes);
246+
if (data.base_profile_delta && data.base_profile_delta.artifact_sizes[idx]) {
247+
td(row, data.base_profile_delta.artifact_sizes[idx].bytes);
248+
}
249+
artifactTable.appendChild(row);
250+
idx += 1;
251+
}
252+
}
253+
254+
function to_object(element) {
255+
if (!element.length) {
256+
element = [
257+
// escape html, to prevent rendering queries like <unknown> as tags
258+
escapeHtml(element.label),
259+
element.self_time,
260+
element.percent_total_time,
261+
element.number_of_cache_misses,
262+
element.number_of_cache_hits,
263+
element.invocation_count,
264+
element.blocked_time,
265+
element.incremental_load_time,
266+
];
267+
}
268+
let [
269+
label, self_time, percent_total_time, _cache_misses,
270+
_cache_hits, invocation_count, _blocked_time,
271+
incremental_load_time
272+
] = element;
273+
return {
274+
label,
275+
self_time,
276+
percent_total_time,
277+
invocation_count,
278+
incremental_load_time,
279+
};
280+
}
281+
282+
var DATA;
283+
284+
function make_data(state) {
285+
let values = Object.assign({
286+
sort_idx: "-2",
287+
}, state);
288+
makeRequest("/self-profile", values).then(function (data) {
289+
DATA = data;
290+
data = JSON.parse(JSON.stringify(DATA)); // deep copy
291+
populate_data(data, values);
292+
});
293+
}
294+
295+
loadState(make_data, true);

site/templates/layout.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
<head>
44
<meta charset="utf-8">
55
<title>rustc performance data</title>
6-
<link rel="stylesheet" type="text/css" href="perf.css">
76
<link rel="alternate icon" type="image/png" href="/favicon-32x32.png">
87
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
8+
<link rel="stylesheet" type="text/css" href="perf.css">
99
{% block head %}{% endblock %}
1010
</head>
1111
<body class="container">

site/templates/pages/bootstrap.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{% extends "layout.html" %}
22
{% block head %}
33
<link rel="stylesheet" href="uPlot.min.css" />
4-
<link rel="stylesheet" type="text/css" href="perf.css" />
54
<style>
65
.uplot {
76
display: inline-block;

site/templates/pages/dashboard.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{% extends "layout.html" %}
22
{% block head %}
3-
<link rel="stylesheet" type="text/css" href="perf.css">
43
<script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.7/highcharts.js"></script>
54
{% endblock %}
65
{% block content %}

0 commit comments

Comments
 (0)