diff --git a/docs/compare.html b/docs/compare.html new file mode 100644 index 000000000..ac5da9d6a --- /dev/null +++ b/docs/compare.html @@ -0,0 +1,371 @@ + + + + +rustc performance data + + + + + + + +
> graphs, compare, + dashboard, status.
+
+

Warning: although measurements known to have high variation are marked with + '?'/'??', this does not mean that unmarked measurements are guaranteed to have + low variation. Verify the measurement against the + + last "noise run" which shows the perf difference of a non-functional change. +

+
+ Filter benchmark builds:
+ Include runs: +
+
Clean
+
Baseline incremental
+
Clean incremental
+
Patched incremental
+
+

See brief explanation at bottom of this page for details on what each run kind means.

+ +
+
+

Commits

+ Commit/Date A:
+ Commit/Date B:
+ +
+ Submit +
+
+
+
+
+

Brief explanation

+

Most benchmarks have at least 4 "runs"

+ +
+ + Fork me on GitHub + + + + + diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 000000000..b8ad23769 Binary files /dev/null and b/docs/favicon.ico differ diff --git a/docs/info.json b/docs/info.json new file mode 100644 index 000000000..fad8e788c --- /dev/null +++ b/docs/info.json @@ -0,0 +1 @@ +{"stats":["cpu-clock","cycles:u","faults","instructions:u","max-rss","task-clock","wall-time"],"as_of":"2020-03-29T09:50:52+00:00"} diff --git a/docs/perf.css b/docs/perf.css new file mode 100644 index 000000000..873d77a41 --- /dev/null +++ b/docs/perf.css @@ -0,0 +1,125 @@ +body { + font-family: monospace; + margin: 3em auto; +} +p { + margin-top: 1.2em; + margin-bottom: 1.2em; +} +span.settings { + display: inline-block; + vertical-align: top; + padding: 10px; +} + +#dates { + text-align: right; +} + +#dates h3 { + text-align: left; +} + +span.compare { + display: inline-block; + vertical-align: top; + padding: 10px; +} +div.submit { + padding: 20px; + padding-top: 10px; + padding-right: 0; + text-align: right; +} +table { + font-size: small; +} +li { + max-width: 580px; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline-offset: -2px; +} +li { + margin-bottom: .5em; +} + +ul { + padding-left: 30px; +} + +h2 { + font-weight: 500; + font-size: 18.5px; /* gridfit */ +} +h3 { + font-weight: 500; +} + +img { + border: 0; +} +.container { + padding-right: 4em; + padding-left: 4em; + margin-right: auto; + margin-left: auto; +} + +.big_summary { + display: block; + margin-top: -20px; + font-size: 15em; + font-weight: 500; + z-index: -1; +} +.positive { + color: red; +} +.negative { + color: green; +} +.neutral { + color: black; +} +.summary_table td { + padding: 4px; +} +.summary_table th { + padding: 4px; +} + +#as-of { + text-align: center; +} + +.compare, .stats { + table-layout: fixed; +} + +.stats td, .compare td, .stats th, .compare th { + padding: 0.3em; +} + +table td, table th { + text-align: right; +} + +.space { + width: 1em; +} + +.group-by { + padding-bottom: 1em; + display: block; +} diff --git a/docs/perfdata b/docs/perfdata new file mode 100644 index 000000000..f36814a32 Binary files /dev/null and b/docs/perfdata differ diff --git a/docs/shared.js b/docs/shared.js new file mode 100644 index 000000000..7fa8a4bef --- /dev/null +++ b/docs/shared.js @@ -0,0 +1,120 @@ +const BASE_URL = window.location.origin + "/perf"; + +function getSelected(name) { + let e = document.getElementById(name); + return e.options[e.selectedIndex].value; +} + +// Get lists of the available crates from the server and make +// the lists of checkboxes and other settings. +// Assumes the initial graph is total/total/by crate +function make_settings(callback) { + let infoURL = 'info.json'; // FIXME use perf-rlo + return fetch(infoURL, {}).then(function(response) { + response.json().then(function(data) { + let phases_html = ""; + for (let stat of data.stats) { + phases_html += ``; + } + let list = document.getElementById("stats"); + if (list) { + list.innerHTML = phases_html; + list.value = 'instructions:u'; + } + document.getElementById("as-of").innerHTML = + "Updated as of: " + (new Date(data.as_of)).toLocaleString(); + callback(); + }); + }, function(err) { + document.getElementById("settings").innerHTML = "Error fetching info"; + console.log("Error fetching info:"); + console.log(err); + }); +} + + +function query_string_for_state(state) { + let result = "?"; + for (let k in state) { + if (result.length > 1) { + result += "&"; + } + // Best known way to check if passed state is a date object. + if (state[k].toISOString) { + result += k + "=" + encodeURIComponent(state[k].toISOString()); + } else if (typeof state[k] == "string") { + result += k + "=" + encodeURIComponent(state[k]); + } else { + result += k + "=" + encodeURIComponent(JSON.stringify(state[k])); + } + } + return result; +} + +function load_state(callback, skip_settings) { + let params = new URLSearchParams(window.location.search.slice(1)); + let state = {}; + for (let param of params) { + let key = param[0]; + let value = param[1]; + if (key === "absolute") { + value = value === "true"; + } + state[key] = value; + } + callback(state); + if (!skip_settings) { + make_settings(() => { + if (state.stat) { + let e = document.getElementById("stats"); + for (let i = 0; i < e.options.length; i++) { + if (e.options[i].text === state.stat) { + e.options[i].selected = true; + break; + } + } + } + }); + } + if (state.start) { + document.getElementById("start-bound").value = state.start; + } + if (state.end) { + document.getElementById("end-bound").value = state.end; + } + if (state.absolute === true || state.absolute === false) { + document.getElementById("absolute").checked = state.absolute; + } else { + // check absolute by default + let element = document.getElementById("absolute"); + if (element) { + element.checked = true; + } + } +} + +// This one is for making the request we send to the backend. +function make_request(path, body) { + return fetch(BASE_URL + path, { + method: "POST", + body: JSON.stringify(body), + mode: "cors" + }).then(response => { + if (response.ok) { + if(MessagePack === undefined) { + alert("msgpack is not loaded"); + return Promise.reject("msgpack is not loaded"); + } + return MessagePack.decodeAsync(response.clone().body).catch(() => { + return response.text().then(data => alert(data)); + }); + } else { + return response.text().then(data => { + alert(data); + return Promise.reject(data); + }); + } + }, err => { + console.log("error fetching ", path, ": ", err); + }); +} diff --git a/site/static/compare.html b/site/static/compare.html index 2db379a4e..ac5da9d6a 100644 --- a/site/static/compare.html +++ b/site/static/compare.html @@ -3,6 +3,56 @@ rustc performance data + + + + @@ -55,9 +105,14 @@

Brief explanation

Fork me on GitHub - diff --git a/site/static/shared.js b/site/static/shared.js index 18631947f..7fa8a4bef 100644 --- a/site/static/shared.js +++ b/site/static/shared.js @@ -1,89 +1,16 @@ -var BASE_URL = window.location.origin + "/perf"; - -function getDate(id) { - var result = document.getElementById(id).value; - var as_date = new Date(result); - if (isNaN(as_date.getTime())) { - return ""; - } else { - return as_date.toISOString(); - } -} - -function getValue(id) { - return document.getElementById(id).value; -} - -function gatherChecks(name) { - if (document.getElementById(name + "-total") && - document.getElementById(name + "-total").checked) { - return { list: "All", content: null }; // Decoded as all variants - } - let result = []; - let elements = document.getElementsByName(name); - for (let element of elements) { - if (element.checked && element.id && element.id != name + "-total") { - result.push(element.id); - } - } - - return { list: "List", content: result }; -} +const BASE_URL = window.location.origin + "/perf"; function getSelected(name) { let e = document.getElementById(name); return e.options[e.selectedIndex].value; } -function setSelected(id, text) { - let e = document.getElementById(id); - for (let i = 0; i < e.options.length; i++) { - if (e.options[i].text === text) { - e.options[i].selected = true; - return; - } - } -} - -function toList(list_object, type) { - if (list_object.list == "All") { - let result = []; - let elements = document.getElementsByName(name); - for (let element of elements) { - if (element.checked && element.id && element.id != `check-${type}-total`) { - result.push(element.id); - } - } - - return result; - } - - return list_object.content; -} - -function addTotalHandler(name) { - var elements = document.getElementsByName(name); - for (var i in elements) { - if (elements[i].id != name + "-total") { - elements[i].onclick = function() { - document.getElementById(name + "-total").checked = false; - }; - } - } - document.getElementById(name + "-total").onclick = function() { - for (var i in elements) { - if (elements[i].id != name + "-total") { - elements[i].checked = false; - } - } - }; -} - // Get lists of the available crates from the server and make // the lists of checkboxes and other settings. // Assumes the initial graph is total/total/by crate function make_settings(callback) { - return fetch(BASE_URL + "/info", {}).then(function(response) { + let infoURL = 'info.json'; // FIXME use perf-rlo + return fetch(infoURL, {}).then(function(response) { response.json().then(function(data) { let phases_html = ""; for (let stat of data.stats) { @@ -105,72 +32,10 @@ function make_settings(callback) { }); } -function truncate_name(name) { - if (name.length > 30) { - return name.substring(0, 30) + "..."; - } - - return name; -} - -function set_date(id, date) { - let d = new Date(date); - if (!Number.isNaN(d.getTime())) { - document.getElementById(id).value = new Date(date).toISOString().split('T')[0]; - } else { - console.warn("could not set", id, "to:", date, "; invalid date"); - } - return document.getElementById(id).value; -} - -function set_value(id, value) { - document.getElementById(id).value = value; -} - -// A bunch of helper functions for helping with keeping URLs up to date and -// interacting with the browser history. - -// Dispatches on query string state. This examines the ?... part of the URL. -// -// The query string may not contain all of the parameters. If it doesn't, we simply pass what -// exists. -function dispatch_on_params(f) { - if (!window.location.search) { - f({}, false); - return; - } - - let params = new URLSearchParams(window.location.search.substring(1)); - let state = {}; - for (let param of params) { - let key = param[0]; - let value = param[1]; - - if (key == "phases" || key == "dates") { - value = JSON.parse(value); - } - - state[key] = value; - } - f(state, false); -} - -// Add an entry into the browser's history to allow the back button to work correctly. -// -// This does not refresh the page in any way. -// -// For more information, see: -// https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method -function push_state_to_history(state) { - var query_string = query_string_for_state(state); - if (query_string !== "") { - history.pushState(state, "", query_string); - } -} function query_string_for_state(state) { - var result = "?"; - for (k in state) { + let result = "?"; + for (let k in state) { if (result.length > 1) { result += "&"; } @@ -192,11 +57,25 @@ function load_state(callback, skip_settings) { for (let param of params) { let key = param[0]; let value = param[1]; - if (key == "absolute") { - value = value == "true" ? true : false; + if (key === "absolute") { + value = value === "true"; } state[key] = value; } + callback(state); + if (!skip_settings) { + make_settings(() => { + if (state.stat) { + let e = document.getElementById("stats"); + for (let i = 0; i < e.options.length; i++) { + if (e.options[i].text === state.stat) { + e.options[i].selected = true; + break; + } + } + } + }); + } if (state.start) { document.getElementById("start-bound").value = state.start; } @@ -212,34 +91,21 @@ function load_state(callback, skip_settings) { element.checked = true; } } - if (!skip_settings) { - make_settings(() => { - if (state.stat) { - setSelected("stats", state.stat); - } - callback(state); - }); - } else { - callback(state); - } } // This one is for making the request we send to the backend. function make_request(path, body) { - if(window.msgpack === undefined) { - alert("msgpack is not loaded, maybe allow scripts from cdnjs.cloudflare.com?"); - return Promise.reject("msgpack is not loaded"); - } - return fetch(BASE_URL + path, { method: "POST", body: JSON.stringify(body), mode: "cors" }).then(response => { if (response.ok) { - return response.clone().arrayBuffer().then((arrayBuffer) => { - return msgpack.decode(new Uint8Array(arrayBuffer)) - }).catch(() => { + if(MessagePack === undefined) { + alert("msgpack is not loaded"); + return Promise.reject("msgpack is not loaded"); + } + return MessagePack.decodeAsync(response.clone().body).catch(() => { return response.text().then(data => alert(data)); }); } else {