mirror of
https://github.com/django-components/django-components.git
synced 2025-08-08 00:07:59 +00:00
feat: benchmarking (#999)
* feat: add benchmarking dashboard, CI hook on PR, and store lifetime results * refactor: change python env to 3.13 in benchmarks * refactor: add verbosity, use 3.11 for benchmarking * fix: OSError: [Errno 7] Argument list too long * refactor: add debug statements * refactor: remove extraneous -e * refactor: fix tests and linter errors * fix: track main package in coverage * refactor: fix test coverage testing * refactor: fix repo owner name in benchmark on pushing comment * refactor: add asv monkeypatch to docs workflow * refactor: temporarily allow building docs in forks * refactor: use py 3.13 for benchmarking * refactor: run only a single benchmark for PRs to speed them up * refactor: install asv in the docs build workflow * refactor: use hatch docs env to generate benhcmarks in docs CI * refactor: more trying * refactor: move tests * Add benchmark results for 0.137 * Trigger Build * Add benchmark results for 0.138 * refactor: set constant machine name when benchmarking * Add benchmark results for 0.139 * refactor: fix issue with paths too long * Add benchmark results for 0.140 * docs: update comment * refactor: remove test benchmarking data * refactor: fix comment * refactor: allow the benchmark workflow to write to PRs * refactor: use personal access token to set up the PR benchmark bot * refactor: split the benchmark PR flow into two to make it work with PRs from forks * refactor: update deprecated actions/upload-artifact@v3 to v4 * refactor: fix missing directory in benchmarking workflow * refactor: fix triggering of second workflow * refactor: fix workflow finally? * docs: add comments to cut-offs and direct people to benchmarks PR --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
dcd4203eea
commit
f36581ed86
90 changed files with 40817 additions and 443 deletions
161
docs/benchmarks/asv.css
Normal file
161
docs/benchmarks/asv.css
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Basic navigation */
|
||||
|
||||
.asv-navigation {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
nav ul li.active a {
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
nav li.active span.navbar-brand {
|
||||
background-color: #e7e7e7;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
nav li.active span.navbar-brand:hover {
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-link {
|
||||
color: #2458D9;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin-bottom: 4px;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
|
||||
.panel-default>.panel-heading,
|
||||
.panel-heading {
|
||||
font-size: 12px;
|
||||
font-weight:bold;
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.btn,
|
||||
.btn-group,
|
||||
.btn-group-vertical>.btn:first-child,
|
||||
.btn-group-vertical>.btn:last-child:not(:first-child),
|
||||
.btn-group-vertical>.btn:last-child {
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-default:focus, .btn-default:active, .btn-default.active {
|
||||
border: none;
|
||||
color: #fff;
|
||||
background-color: #99bfcd;
|
||||
}
|
||||
|
||||
#range {
|
||||
font-family: monospace;
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
font-size: 12px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
min-width: 100px;
|
||||
max-width: 800px;
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/* Benchmark tree */
|
||||
|
||||
.nav-list {
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.nav-list>li {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.nav-list>li>a {
|
||||
padding: 0;
|
||||
padding-left: 5px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-list>li>a:focus {
|
||||
color: #fff;
|
||||
background-color: #99bfcd;
|
||||
box-shadow: inset 0 3px 5px rgba(0,0,0,.125);
|
||||
}
|
||||
|
||||
.nav-list>li>.nav-header {
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.caret-right {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 2px;
|
||||
vertical-align: middle;
|
||||
border-left: 4px solid;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-top: 4px solid transparent;
|
||||
}
|
||||
|
||||
/* Summary page */
|
||||
|
||||
.benchmark-group > h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.benchmark-container {
|
||||
width: 300px;
|
||||
height: 116px;
|
||||
padding: 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.benchmark-container:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.benchmark-plot {
|
||||
width: 292px;
|
||||
height: 88px;
|
||||
}
|
||||
|
||||
.benchmark-text {
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
width: 292px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#extra-buttons {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#extra-buttons a {
|
||||
border: solid 1px #ccc;
|
||||
}
|
525
docs/benchmarks/asv.js
Normal file
525
docs/benchmarks/asv.js
Normal file
|
@ -0,0 +1,525 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
/* GLOBAL STATE */
|
||||
/* The index.json content as returned from the server */
|
||||
var main_timestamp = '';
|
||||
var main_json = {};
|
||||
/* Extra pages: {name: show_function} */
|
||||
var loaded_pages = {};
|
||||
/* Previous window scroll positions */
|
||||
var window_scroll_positions = {};
|
||||
/* Previous window hash location */
|
||||
var window_last_location = null;
|
||||
/* Graph data cache */
|
||||
var graph_cache = {};
|
||||
var graph_cache_max_size = 5;
|
||||
|
||||
var colors = [
|
||||
'#247AAD',
|
||||
'#E24A33',
|
||||
'#988ED5',
|
||||
'#777777',
|
||||
'#FBC15E',
|
||||
'#8EBA42',
|
||||
'#FFB5B8'
|
||||
];
|
||||
|
||||
var time_units = [
|
||||
['ps', 'picoseconds', 0.000000000001],
|
||||
['ns', 'nanoseconds', 0.000000001],
|
||||
['μs', 'microseconds', 0.000001],
|
||||
['ms', 'milliseconds', 0.001],
|
||||
['s', 'seconds', 1],
|
||||
['m', 'minutes', 60],
|
||||
['h', 'hours', 60 * 60],
|
||||
['d', 'days', 60 * 60 * 24],
|
||||
['w', 'weeks', 60 * 60 * 24 * 7],
|
||||
['y', 'years', 60 * 60 * 24 * 7 * 52],
|
||||
['C', 'centuries', 60 * 60 * 24 * 7 * 52 * 100]
|
||||
];
|
||||
|
||||
var mem_units = [
|
||||
['', 'bytes', 1],
|
||||
['k', 'kilobytes', 1000],
|
||||
['M', 'megabytes', 1000000],
|
||||
['G', 'gigabytes', 1000000000],
|
||||
['T', 'terabytes', 1000000000000]
|
||||
];
|
||||
|
||||
function pretty_second(x) {
|
||||
for (var i = 0; i < time_units.length - 1; ++i) {
|
||||
if (Math.abs(x) < time_units[i+1][2]) {
|
||||
return (x / time_units[i][2]).toFixed(3) + time_units[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
return 'inf';
|
||||
}
|
||||
|
||||
function pretty_byte(x) {
|
||||
for (var i = 0; i < mem_units.length - 1; ++i) {
|
||||
if (Math.abs(x) < mem_units[i+1][2]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
return x + '';
|
||||
}
|
||||
return (x / mem_units[i][2]).toFixed(3) + mem_units[i][0];
|
||||
}
|
||||
|
||||
function pretty_unit(x, unit) {
|
||||
if (unit == "seconds") {
|
||||
return pretty_second(x);
|
||||
}
|
||||
else if (unit == "bytes") {
|
||||
return pretty_byte(x);
|
||||
}
|
||||
else if (unit && unit != "unit") {
|
||||
return '' + x.toPrecision(3) + ' ' + unit;
|
||||
}
|
||||
else {
|
||||
return '' + x.toPrecision(3);
|
||||
}
|
||||
}
|
||||
|
||||
function pad_left(s, c, num) {
|
||||
s = '' + s;
|
||||
while (s.length < num) {
|
||||
s = c + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function format_date_yyyymmdd(date) {
|
||||
return (pad_left(date.getFullYear(), '0', 4)
|
||||
+ '-' + pad_left(date.getMonth() + 1, '0', 2)
|
||||
+ '-' + pad_left(date.getDate(), '0', 2));
|
||||
}
|
||||
|
||||
function format_date_yyyymmdd_hhmm(date) {
|
||||
return (format_date_yyyymmdd(date) + ' '
|
||||
+ pad_left(date.getHours(), '0', 2)
|
||||
+ ':' + pad_left(date.getMinutes(), '0', 2));
|
||||
}
|
||||
|
||||
/* Convert a flat index to permutation to the corresponding value */
|
||||
function param_selection_from_flat_idx(params, idx) {
|
||||
var selection = [];
|
||||
if (idx < 0) {
|
||||
idx = 0;
|
||||
}
|
||||
for (var k = params.length-1; k >= 0; --k) {
|
||||
var j = idx % params[k].length;
|
||||
selection.unshift([j]);
|
||||
idx = (idx - j) / params[k].length;
|
||||
}
|
||||
selection.unshift([null]);
|
||||
return selection;
|
||||
}
|
||||
|
||||
/* Convert a benchmark parameter value from their native Python
|
||||
repr format to a number or a string, ready for presentation */
|
||||
function convert_benchmark_param_value(value_repr) {
|
||||
var match = Number(value_repr);
|
||||
if (!isNaN(match)) {
|
||||
return match;
|
||||
}
|
||||
|
||||
/* Python str */
|
||||
match = value_repr.match(/^'(.+)'$/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
/* Python unicode */
|
||||
match = value_repr.match(/^u'(.+)'$/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
/* Python class */
|
||||
match = value_repr.match(/^<class '(.+)'>$/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
return value_repr;
|
||||
}
|
||||
|
||||
/* Convert loaded graph data to a format flot understands, by
|
||||
treating either time or one of the parameters as x-axis,
|
||||
and selecting only one value of the remaining axes */
|
||||
function filter_graph_data(raw_series, x_axis, other_indices, params) {
|
||||
if (params.length == 0) {
|
||||
/* Simple time series */
|
||||
return raw_series;
|
||||
}
|
||||
|
||||
/* Compute position of data entry in the results list,
|
||||
and stride corresponding to plot x-axis parameter */
|
||||
var stride = 1;
|
||||
var param_stride = 0;
|
||||
var param_idx = 0;
|
||||
for (var k = params.length - 1; k >= 0; --k) {
|
||||
if (k == x_axis - 1) {
|
||||
param_stride = stride;
|
||||
}
|
||||
else {
|
||||
param_idx += other_indices[k + 1] * stride;
|
||||
}
|
||||
stride *= params[k].length;
|
||||
}
|
||||
|
||||
if (x_axis == 0) {
|
||||
/* x-axis is time axis */
|
||||
var series = new Array(raw_series.length);
|
||||
for (var k = 0; k < raw_series.length; ++k) {
|
||||
if (raw_series[k][1] === null) {
|
||||
series[k] = [raw_series[k][0], null];
|
||||
} else {
|
||||
series[k] = [raw_series[k][0],
|
||||
raw_series[k][1][param_idx]];
|
||||
}
|
||||
}
|
||||
return series;
|
||||
}
|
||||
else {
|
||||
/* x-axis is some parameter axis */
|
||||
var time_idx = null;
|
||||
if (other_indices[0] === null) {
|
||||
time_idx = raw_series.length - 1;
|
||||
}
|
||||
else {
|
||||
/* Need to search for the correct time value */
|
||||
for (var k = 0; k < raw_series.length; ++k) {
|
||||
if (raw_series[k][0] == other_indices[0]) {
|
||||
time_idx = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (time_idx === null) {
|
||||
/* No data points */
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
var x_values = params[x_axis - 1];
|
||||
var series = new Array(x_values.length);
|
||||
for (var k = 0; k < x_values.length; ++k) {
|
||||
if (raw_series[time_idx][1] === null) {
|
||||
series[k] = [convert_benchmark_param_value(x_values[k]),
|
||||
null];
|
||||
}
|
||||
else {
|
||||
series[k] = [convert_benchmark_param_value(x_values[k]),
|
||||
raw_series[time_idx][1][param_idx]];
|
||||
}
|
||||
param_idx += param_stride;
|
||||
}
|
||||
return series;
|
||||
}
|
||||
}
|
||||
|
||||
function filter_graph_data_idx(raw_series, x_axis, flat_idx, params) {
|
||||
var selection = param_selection_from_flat_idx(params, flat_idx);
|
||||
var flat_selection = [];
|
||||
$.each(selection, function(i, v) {
|
||||
flat_selection.push(v[0]);
|
||||
});
|
||||
return filter_graph_data(raw_series, x_axis, flat_selection, params);
|
||||
}
|
||||
|
||||
/* Escape special characters in graph item file names.
|
||||
The implementation must match asv.util.sanitize_filename */
|
||||
function sanitize_filename(name) {
|
||||
var bad_re = /[<>:"\/\\^|?*\x00-\x1f]/g;
|
||||
var bad_names = ["CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3",
|
||||
"COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1",
|
||||
"LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8",
|
||||
"LPT9"];
|
||||
name = name.replace(bad_re, "_");
|
||||
if (bad_names.indexOf(name.toUpperCase()) != -1) {
|
||||
name = name + "_";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Given a specific group of parameters, generate the URL to
|
||||
use to load that graph.
|
||||
The implementation must match asv.graph.Graph.get_file_path
|
||||
*/
|
||||
function graph_to_path(benchmark_name, state) {
|
||||
var parts = [];
|
||||
$.each(state, function(key, value) {
|
||||
var part;
|
||||
if (value === null) {
|
||||
part = key + "-null";
|
||||
} else if (value) {
|
||||
part = key + "-" + value;
|
||||
} else {
|
||||
part = key;
|
||||
}
|
||||
parts.push(sanitize_filename('' + part));
|
||||
});
|
||||
parts.sort();
|
||||
parts.splice(0, 0, "graphs");
|
||||
parts.push(sanitize_filename(benchmark_name));
|
||||
|
||||
/* Escape URI components */
|
||||
parts = $.map(parts, function (val) { return encodeURIComponent(val); });
|
||||
return parts.join('/') + ".json";
|
||||
}
|
||||
|
||||
/*
|
||||
Load and cache graph data (on javascript side)
|
||||
*/
|
||||
function load_graph_data(url, success, failure) {
|
||||
var dfd = $.Deferred();
|
||||
if (graph_cache[url]) {
|
||||
setTimeout(function() {
|
||||
dfd.resolve(graph_cache[url]);
|
||||
}, 1);
|
||||
}
|
||||
else {
|
||||
$.ajax({
|
||||
url: url + '?timestamp=' + $.asv.main_timestamp,
|
||||
dataType: "json",
|
||||
cache: true
|
||||
}).done(function(data) {
|
||||
if (Object.keys(graph_cache).length > graph_cache_max_size) {
|
||||
$.each(Object.keys(graph_cache), function (i, key) {
|
||||
delete graph_cache[key];
|
||||
});
|
||||
}
|
||||
graph_cache[url] = data;
|
||||
dfd.resolve(data);
|
||||
}).fail(function() {
|
||||
dfd.reject();
|
||||
});
|
||||
}
|
||||
return dfd.promise();
|
||||
}
|
||||
|
||||
/*
|
||||
Parse hash string, assuming format similar to standard URL
|
||||
query strings
|
||||
*/
|
||||
function parse_hash_string(str) {
|
||||
var info = {location: [''], params: {}};
|
||||
|
||||
if (str && str[0] == '#') {
|
||||
str = str.slice(1);
|
||||
}
|
||||
if (str && str[0] == '/') {
|
||||
str = str.slice(1);
|
||||
}
|
||||
|
||||
var match = str.match(/^([^?]*?)\?/);
|
||||
if (match) {
|
||||
info['location'] = decodeURIComponent(match[1]).replace(/\/+/, '/').split('/');
|
||||
var rest = str.slice(match[1].length+1);
|
||||
var parts = rest.split('&');
|
||||
for (var i = 0; i < parts.length; ++i) {
|
||||
var part = parts[i].split('=');
|
||||
if (part.length != 2) {
|
||||
continue;
|
||||
}
|
||||
var key = decodeURIComponent(part[0].replace(/\+/g, " "));
|
||||
var value = decodeURIComponent(part[1].replace(/\+/g, " "));
|
||||
if (value == '[none]') {
|
||||
value = null;
|
||||
}
|
||||
if (info['params'][key] === undefined) {
|
||||
info['params'][key] = [value];
|
||||
}
|
||||
else {
|
||||
info['params'][key].push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
info['location'] = decodeURIComponent(str).replace(/\/+/, '/').split('/');
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/*
|
||||
Generate a hash string, inverse of parse_hash_string
|
||||
*/
|
||||
function format_hash_string(info) {
|
||||
var parts = info['params'];
|
||||
var str = '#' + info['location'];
|
||||
|
||||
if (parts) {
|
||||
str = str + '?';
|
||||
var first = true;
|
||||
$.each(parts, function (key, values) {
|
||||
$.each(values, function (idx, value) {
|
||||
if (!first) {
|
||||
str = str + '&';
|
||||
}
|
||||
if (value === null) {
|
||||
value = '[none]';
|
||||
}
|
||||
str = str + encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
||||
first = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
Dealing with sub-pages
|
||||
*/
|
||||
|
||||
function show_page(name, params) {
|
||||
if (loaded_pages[name] !== undefined) {
|
||||
$("#nav ul li.active").removeClass('active');
|
||||
$("#nav-li-" + name).addClass('active');
|
||||
$("#graph-display").hide();
|
||||
$("#summarygrid-display").hide();
|
||||
$("#summarylist-display").hide();
|
||||
$('#regressions-display').hide();
|
||||
$('.tooltip').remove();
|
||||
loaded_pages[name](params);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hashchange() {
|
||||
var info = parse_hash_string(window.location.hash);
|
||||
|
||||
/* Keep track of window scroll position; makes the back-button work */
|
||||
var old_scroll_pos = window_scroll_positions[info.location.join('/')];
|
||||
window_scroll_positions[window_last_location] = $(window).scrollTop();
|
||||
window_last_location = info.location.join('/');
|
||||
|
||||
/* Redirect to correct handler */
|
||||
if (show_page(info.location, info.params)) {
|
||||
/* show_page does the work */
|
||||
}
|
||||
else {
|
||||
/* Display benchmark page */
|
||||
info.params['benchmark'] = info.location[0];
|
||||
show_page('graphdisplay', info.params);
|
||||
}
|
||||
|
||||
/* Scroll back to previous position, if any */
|
||||
if (old_scroll_pos !== undefined) {
|
||||
$(window).scrollTop(old_scroll_pos);
|
||||
}
|
||||
}
|
||||
|
||||
function get_commit_hash(revision) {
|
||||
var commit_hash = main_json.revision_to_hash[revision];
|
||||
if (commit_hash) {
|
||||
// Return printable commit hash
|
||||
commit_hash = commit_hash.slice(0, main_json.hash_length);
|
||||
}
|
||||
return commit_hash;
|
||||
}
|
||||
|
||||
function get_revision(commit_hash) {
|
||||
var rev = null;
|
||||
$.each(main_json.revision_to_hash, function(revision, full_commit_hash) {
|
||||
if (full_commit_hash.startsWith(commit_hash)) {
|
||||
rev = revision;
|
||||
// break the $.each loop
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return rev;
|
||||
}
|
||||
|
||||
function init_index() {
|
||||
/* Fetch the main index.json and then set up the page elements
|
||||
based on it. */
|
||||
$.ajax({
|
||||
url: "index.json" + '?timestamp=' + $.asv.main_timestamp,
|
||||
dataType: "json",
|
||||
cache: true
|
||||
}).done(function (index) {
|
||||
main_json = index;
|
||||
$.asv.main_json = index;
|
||||
|
||||
/* Page title */
|
||||
var project_name = $("#project-name")[0];
|
||||
project_name.textContent = index.project;
|
||||
project_name.setAttribute("href", index.project_url);
|
||||
$("#project-name").textContent = index.project;
|
||||
document.title = "airspeed velocity of an unladen " + index.project;
|
||||
|
||||
$(window).on('hashchange', hashchange);
|
||||
|
||||
$('#graph-display').hide();
|
||||
$('#regressions-display').hide();
|
||||
$('#summarygrid-display').hide();
|
||||
$('#summarylist-display').hide();
|
||||
|
||||
hashchange();
|
||||
}).fail(function () {
|
||||
$.asv.ui.network_error();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
/* Fetch the info.json */
|
||||
$.ajax({
|
||||
url: "info.json",
|
||||
dataType: "json",
|
||||
cache: false
|
||||
}).done(function (info) {
|
||||
main_timestamp = info['timestamp'];
|
||||
$.asv.main_timestamp = main_timestamp;
|
||||
init_index();
|
||||
}).fail(function () {
|
||||
$.asv.ui.network_error();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set up $.asv
|
||||
*/
|
||||
|
||||
this.register_page = function(name, show_function) {
|
||||
loaded_pages[name] = show_function;
|
||||
}
|
||||
this.parse_hash_string = parse_hash_string;
|
||||
this.format_hash_string = format_hash_string;
|
||||
|
||||
this.filter_graph_data = filter_graph_data;
|
||||
this.filter_graph_data_idx = filter_graph_data_idx;
|
||||
this.convert_benchmark_param_value = convert_benchmark_param_value;
|
||||
this.param_selection_from_flat_idx = param_selection_from_flat_idx;
|
||||
this.graph_to_path = graph_to_path;
|
||||
this.load_graph_data = load_graph_data;
|
||||
this.get_commit_hash = get_commit_hash;
|
||||
this.get_revision = get_revision;
|
||||
|
||||
this.main_timestamp = main_timestamp; /* Updated after info.json loads */
|
||||
this.main_json = main_json; /* Updated after index.json loads */
|
||||
|
||||
this.format_date_yyyymmdd = format_date_yyyymmdd;
|
||||
this.format_date_yyyymmdd_hhmm = format_date_yyyymmdd_hhmm;
|
||||
this.pretty_unit = pretty_unit;
|
||||
this.time_units = time_units;
|
||||
this.mem_units = mem_units;
|
||||
|
||||
this.colors = colors;
|
||||
|
||||
$.asv = this;
|
||||
|
||||
|
||||
/*
|
||||
Launch it
|
||||
*/
|
||||
|
||||
init();
|
||||
});
|
231
docs/benchmarks/asv_ui.js
Normal file
231
docs/benchmarks/asv_ui.js
Normal file
|
@ -0,0 +1,231 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
function make_panel(nav, heading) {
|
||||
var panel = $('<div class="panel panel-default"/>');
|
||||
nav.append(panel);
|
||||
var panel_header = $(
|
||||
'<div class="panel-heading">' + heading + '</div>');
|
||||
panel.append(panel_header);
|
||||
var panel_body = $('<div class="panel-body"/>');
|
||||
panel.append(panel_body);
|
||||
return panel_body;
|
||||
}
|
||||
|
||||
function make_value_selector_panel(nav, heading, values, setup_callback) {
|
||||
var panel_body = make_panel(nav, heading);
|
||||
var vertical = false;
|
||||
var buttons = $('<div class="btn-group" ' +
|
||||
'data-toggle="buttons"/>');
|
||||
|
||||
panel_body.append(buttons);
|
||||
|
||||
$.each(values, function (idx, value) {
|
||||
var button = $(
|
||||
'<a class="btn btn-default btn-xs active" role="button"/>');
|
||||
setup_callback(idx, value, button);
|
||||
buttons.append(button);
|
||||
});
|
||||
|
||||
return panel_body;
|
||||
}
|
||||
|
||||
function reflow_value_selector_panels(no_timeout) {
|
||||
$('.panel').each(function (i, panel_obj) {
|
||||
var panel = $(panel_obj);
|
||||
panel.find('.btn-group').each(function (i, buttons_obj) {
|
||||
var buttons = $(buttons_obj);
|
||||
var width = 0;
|
||||
|
||||
if (buttons.hasClass('reflow-done')) {
|
||||
/* already processed */
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(buttons.children(), function(idx, value) {
|
||||
width += value.scrollWidth;
|
||||
});
|
||||
|
||||
var max_width = panel_obj.clientWidth;
|
||||
|
||||
if (width >= max_width) {
|
||||
buttons.addClass("btn-group-vertical");
|
||||
buttons.css("width", "100%");
|
||||
buttons.css("max-height", "20ex");
|
||||
buttons.css("overflow-y", "auto");
|
||||
}
|
||||
else {
|
||||
buttons.addClass("btn-group-justified");
|
||||
}
|
||||
|
||||
/* The widths can be zero if the UI is not fully layouted yet,
|
||||
so mark the adjustment complete only if this is not the case */
|
||||
if (width > 0 && max_width > 0) {
|
||||
buttons.addClass("reflow-done");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!no_timeout) {
|
||||
/* Call again asynchronously, in case the UI was not fully layouted yet */
|
||||
setTimeout(function() { $.asv.ui.reflow_value_selector_panels(true); }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function network_error(ajax, status, error) {
|
||||
$("#error-message").text(
|
||||
"Error fetching content. " +
|
||||
"Perhaps web server has gone down.");
|
||||
$("#error").modal('show');
|
||||
}
|
||||
|
||||
function hover_graph(element, graph_url, benchmark_basename, parameter_idx, revisions) {
|
||||
/* Show the summary graph as a popup */
|
||||
var plot_div = $('<div/>');
|
||||
plot_div.css('width', '11.8em');
|
||||
plot_div.css('height', '7em');
|
||||
plot_div.css('border', '2px solid black');
|
||||
plot_div.css('background-color', 'white');
|
||||
|
||||
function update_plot() {
|
||||
var markings = [];
|
||||
|
||||
if (revisions) {
|
||||
$.each(revisions, function(i, revs) {
|
||||
var rev_a = revs[0];
|
||||
var rev_b = revs[1];
|
||||
|
||||
if (rev_a !== null) {
|
||||
markings.push({ color: '#d00', lineWidth: 2, xaxis: { from: rev_a, to: rev_a }});
|
||||
markings.push({ color: "rgba(255,0,0,0.1)", xaxis: { from: rev_a, to: rev_b }});
|
||||
}
|
||||
markings.push({ color: '#d00', lineWidth: 2, xaxis: { from: rev_b, to: rev_b }});
|
||||
});
|
||||
}
|
||||
|
||||
$.asv.load_graph_data(
|
||||
graph_url
|
||||
).done(function (data) {
|
||||
var params = $.asv.main_json.benchmarks[benchmark_basename].params;
|
||||
data = $.asv.filter_graph_data_idx(data, 0, parameter_idx, params);
|
||||
var options = {
|
||||
colors: ['#000'],
|
||||
series: {
|
||||
lines: {
|
||||
show: true,
|
||||
lineWidth: 2
|
||||
},
|
||||
shadowSize: 0
|
||||
},
|
||||
grid: {
|
||||
borderWidth: 1,
|
||||
margin: 0,
|
||||
labelMargin: 0,
|
||||
axisMargin: 0,
|
||||
minBorderMargin: 0,
|
||||
markings: markings,
|
||||
},
|
||||
xaxis: {
|
||||
ticks: [],
|
||||
},
|
||||
yaxis: {
|
||||
ticks: [],
|
||||
min: 0
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
};
|
||||
var plot = $.plot(plot_div, [{data: data}], options);
|
||||
}).fail(function () {
|
||||
// TODO: Handle failure
|
||||
});
|
||||
|
||||
return plot_div;
|
||||
}
|
||||
|
||||
element.popover({
|
||||
placement: 'left auto',
|
||||
trigger: 'hover',
|
||||
html: true,
|
||||
delay: 50,
|
||||
content: $('<div/>').append(plot_div)
|
||||
});
|
||||
|
||||
element.on('show.bs.popover', update_plot);
|
||||
}
|
||||
|
||||
function hover_summary_graph(element, benchmark_basename) {
|
||||
/* Show the summary graph as a popup */
|
||||
var plot_div = $('<div/>');
|
||||
plot_div.css('width', '11.8em');
|
||||
plot_div.css('height', '7em');
|
||||
plot_div.css('border', '2px solid black');
|
||||
plot_div.css('background-color', 'white');
|
||||
|
||||
function update_plot() {
|
||||
var markings = [];
|
||||
|
||||
$.asv.load_graph_data(
|
||||
'graphs/summary/' + benchmark_basename + '.json'
|
||||
).done(function (data) {
|
||||
var options = {
|
||||
colors: $.asv.colors,
|
||||
series: {
|
||||
lines: {
|
||||
show: true,
|
||||
lineWidth: 2
|
||||
},
|
||||
shadowSize: 0
|
||||
},
|
||||
grid: {
|
||||
borderWidth: 1,
|
||||
margin: 0,
|
||||
labelMargin: 0,
|
||||
axisMargin: 0,
|
||||
minBorderMargin: 0,
|
||||
markings: markings,
|
||||
},
|
||||
xaxis: {
|
||||
ticks: [],
|
||||
},
|
||||
yaxis: {
|
||||
ticks: [],
|
||||
min: 0
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
};
|
||||
var plot = $.plot(plot_div, [{data: data}], options);
|
||||
}).fail(function () {
|
||||
// TODO: Handle failure
|
||||
});
|
||||
|
||||
return plot_div;
|
||||
}
|
||||
|
||||
element.popover({
|
||||
placement: 'left auto',
|
||||
trigger: 'hover',
|
||||
html: true,
|
||||
delay: 50,
|
||||
content: $('<div/>').append(plot_div)
|
||||
});
|
||||
|
||||
element.on('show.bs.popover', update_plot);
|
||||
}
|
||||
|
||||
/*
|
||||
Set up $.asv.ui
|
||||
*/
|
||||
|
||||
this.network_error = network_error;
|
||||
this.make_panel = make_panel;
|
||||
this.make_value_selector_panel = make_value_selector_panel;
|
||||
this.reflow_value_selector_panels = reflow_value_selector_panels;
|
||||
this.hover_graph = hover_graph;
|
||||
this.hover_summary_graph = hover_summary_graph;
|
||||
|
||||
$.asv.ui = this;
|
||||
});
|
23
docs/benchmarks/error.html
Normal file
23
docs/benchmarks/error.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>airspeed velocity error</title>
|
||||
<link rel="shortcut icon" href="swallow.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>
|
||||
<img src="swallow.png" width="22" height="22" alt="swallow"></img>
|
||||
Can not determine continental origin of swallow.
|
||||
</h1>
|
||||
|
||||
<h3>
|
||||
One or more external (JavaScript) dependencies of airspeed velocity failed to load.
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Make sure you have an active internet connection and enable 3rd-party scripts
|
||||
in your browser the first time you load airspeed velocity.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
1427
docs/benchmarks/graphdisplay.js
Normal file
1427
docs/benchmarks/graphdisplay.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1 @@
|
|||
[[1566, [52121600.0, 54030336.0]], [1569, [52006912.0, 54030336.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [52129792.0, 54525952.0]], [1569, [52019200.0, 54542336.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [43671552.0, 43925504.0]], [1569, [43667456.0, 43921408.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [43675648.0, 43929600.0]], [1569, [43671552.0, 43925504.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.06844023999997262, 0.25948228500001846]], [1569, [0.0695505670000216, 0.2585547080000197]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.03282115399997565, 0.1461098879999838]], [1569, [0.03280580699998836, 0.14556000400000357]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.0035044859999970868, 0.004806205000022601]], [1569, [0.003512746000012612, 0.004752005000000281]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [9.84330000051159e-05, 0.000542360999986613]], [1569, [9.899399998403169e-05, 0.0005454930000041713]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.21055065100000547, 0.20605139500003133]], [1569, [0.20886826499997824, 0.20461195600000792]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.19086866300000338], [1569, 0.1891247499999622]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [54018048.0, 53542912.0]], [1569, [53940224.0, 53530624.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [54571008.0, 54530048.0]], [1569, [54566912.0, 54525952.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [43925504.0, 43925504.0]], [1569, [43921408.0, 43687936.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [43929600.0, 43929600.0]], [1569, [43925504.0, 43925504.0]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.2582084590000022, 0.2630794039999955]], [1569, [0.2609166309999864, 0.26201485799998636]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.14612163999998984, 0.15001642000004267]], [1569, [0.14627813999999262, 0.15037803699999586]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.004762013999993542, 0.004786298999988503]], [1569, [0.004790214000024662, 0.004819428000018888]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.0005448759999922004, 0.0005334049999987656]], [1569, [0.0005436999999801628, 0.0005416959999706705]]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, [0.2058522649999759, 0.2053180329999691]], [1569, [0.20448447999996233, 0.2037191150000126]]]
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
[[1566, 53067386.97974115], [1569, 53008970.27562818]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 53314412.08868371], [1569, 53265830.36855053]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 43798343.942005485], [1569, 43794247.92479085]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 43802439.95921688], [1569, 43798343.942005485]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.13326301010086242], [1569, 0.13409931596367813]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.06924951360815947], [1569, 0.06910291888293614]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.0041040563026955666], [1569, 0.0040856561964745545]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.00023105458297652734], [1569, 0.00023238014982717938]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.20828887477903343], [1569, 0.20672915674372966]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.19086866300000338], [1569, 0.1891247499999622]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 53779955.28517828], [1569, 53735033.72493383]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 54550524.155578785], [1569, 54546428.1552901]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 43925504.00000001], [1569, 43804516.45360199]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 43929599.99999999], [1569, 43925504.00000001]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.2606325526511949], [1569, 0.26146516789296487]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.14805622350084952], [1569, 0.1483139223040422]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.004774141058462804], [1569, 0.004804798796807347]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.0005391099913516415], [1569, 0.0005426970749629188]]
|
|
@ -0,0 +1 @@
|
|||
[[1566, 0.20558497546849924], [1569, 0.20410143874267547]]
|
161
docs/benchmarks/index.html
Normal file
161
docs/benchmarks/index.html
Normal file
|
@ -0,0 +1,161 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>airspeed velocity</title>
|
||||
<script type="text/javascript">
|
||||
function js_load_failure() {
|
||||
window.location = "error.html";
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js" integrity="sha512-eO1AKNIv7KSFl5n81oHCKnYLMi8UV4wWD1TcLYKNTssoECDuiGhoRsQkdiZkl8VUjoms2SeJY7zTSw5noGSqbQ==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.time.min.js" integrity="sha512-lcRowrkiQvFli9HkuJ2Yr58iEwAtzhFNJ1Galsko4SJDhcZfUub8UxGlMQIsMvARiTqx2pm7g6COxJozihOixA==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.selection.min.js" integrity="sha512-3EUG0t3qfbLaGN3FXO86i+57nvxHOXvIb/xMSKRrCuX/HXdn1bkbqwAeLd6U1PDmuEB2cnKhfM+SGLAVQbyjWQ==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.categories.min.js" integrity="sha512-x4QGSZkQ57pNuICMFFevIhDer5NVB5eJCRmENlCdJukMs8xWFH8OHfzWQVSkl9VQ4+4upPPTkHSAewR6KNMjGA==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script language="javascript" type="text/javascript" src="jquery.flot.axislabels.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/flot-orderbars@1.0.0/js/jquery.flot.orderBars.js" integrity="sha256-OXNbT0b5b/TgglckAfR8VaJ2ezZv0dHoIeRKjYMKEr8=" crossorigin="anonymous" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stupidtable/1.0.1/stupidtable.min.js" integrity="sha512-GM3Ds3dUrgkpKVXc+4RxKbQDoeTemdlzXxn5d/QCOJT6EFdEufu1UTVBpIFDLd6YjIhSThNe+zpo1mwqzNq4GQ==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js" integrity="sha512-8pbzenDolL1l5OPSsoURCx9TEdMFTaeFipASVrMYKhuYtly+k3tcsQYliOEKTmuB1t7yuzAiVo+yd7SJz+ijFQ==" crossorigin="anonymous" referrerpolicy="no-referrer" onerror="js_load_failure()"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.1.1/dist/js/bootstrap.min.js" integrity="sha256-iY0FoX8s/FEg3c26R6iFw3jAtGbzDwcA5QJ1fiS0A6E=" crossorigin="anonymous" onerror="js_load_failure()"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.1.1/dist/css/bootstrap.min.css" integrity="sha256-6VA0SGkrc43SYPvX98q/LhHwm2APqX5us6Vuulsafps=" crossorigin="anonymous">
|
||||
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="asv.js">
|
||||
</script>
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="asv_ui.js">
|
||||
</script>
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="summarygrid.js">
|
||||
</script>
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="summarylist.js">
|
||||
</script>
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="graphdisplay.js">
|
||||
</script>
|
||||
<script language="javascript" type="text/javascript"
|
||||
src="regressions.js">
|
||||
</script>
|
||||
<link href="asv.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="regressions.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="summarylist.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="shortcut icon" href="swallow.ico"/>
|
||||
<link rel="alternate" type="application/atom+xml" title="Regressions" href="regressions.xml"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="nav" class="navbar navbar-left navbar-default navbar-fixed-top" role="navigation">
|
||||
<ul class="nav navbar-nav navbar-left">
|
||||
<li>
|
||||
<p class="navbar-text">
|
||||
<a href="http://github.com/airspeed-velocity/asv/" class="navbar-link" target="_blank"><img src="swallow.png" width="22" height="22" alt="swallow"></img>airspeed velocity</a>
|
||||
of an unladen
|
||||
<a id="project-name" href="#" class="navbar-link" target="_blank">project</a>
|
||||
</p>
|
||||
</li>
|
||||
<li id="nav-li-" class="active"><a href="#/">Benchmark grid</a></li>
|
||||
<li id="nav-li-summarylist"><a href="#/summarylist">Benchmark list</a></li>
|
||||
<li id="nav-li-regressions"><a href="#/regressions">Regressions</a></li>
|
||||
<li id="nav-li-graphdisplay">
|
||||
<span class="navbar-brand" id="title">
|
||||
benchmark
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div id="summarygrid-display" style="position: absolute; left: 0; top: 55px; width: 100%; height: 100%">
|
||||
</div>
|
||||
<div id="summarylist-display" style="width: 100%; height: 100%">
|
||||
<div id="summarylist-navigation" class="asv-navigation" style="position: absolute; left: 0; top: 55px; bottom: 0; width: 200px; overflow-y: scroll">
|
||||
</div>
|
||||
<div id="summarylist-body" style="position: absolute; left: 200px; top: 55px; bottom: 0px; right: 0px; overflow-y: scroll;">
|
||||
</div>
|
||||
</div>
|
||||
<div id="graph-display" style="width: 100%; height: 100%;">
|
||||
<div id="graphdisplay-navigation" class="asv-navigation" style="position: absolute; left: 0; top: 55px; bottom: 0; width: 200px; overflow-y: scroll">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
commits
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<input id="range" type="text" class="form-control" size="24" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
plot settings
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="btn-group-vertical" style="width: 100%" data-toggle="buttons">
|
||||
<a id="log-scale" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Use a logarithmic scale on the y-axis">
|
||||
log scale
|
||||
</a>
|
||||
<a id="zoom-y-axis" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Zoom y axis to the range of the data, rather than down to zero.">
|
||||
zoom <i>y</i> axis
|
||||
</a>
|
||||
<a id="reference" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Select a reference point">
|
||||
reference
|
||||
</a>
|
||||
<a id="even-spacing" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Space commits evenly, rather than by revision, along the x-axis">
|
||||
even commit spacing
|
||||
</a>
|
||||
<a id="date-scale" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Space commits by commit date along the x-axis">
|
||||
date scale
|
||||
</a>
|
||||
<a id="show-legend" class="btn btn-default btn-xs" role="button"
|
||||
data-toggle="tooltip" data-placement="right"
|
||||
title="Show legend in the graph">
|
||||
legend
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="position: absolute; left: 220px; top: 60px; bottom: 10px; right: 20px;">
|
||||
<div id="graph">
|
||||
<div style="position: absolute; top: 48px; left: 0; right: 0; bottom: 100px;">
|
||||
<div id="main-graph" style="min-height: 100px; width: 100%; height: 100%"></div>
|
||||
</div>
|
||||
<div style="position: absolute; height: 100px; left: 0; right: 0; bottom: 0; padding-top: 24px">
|
||||
<div id="overview" style="min-height: 100px; width: 100%; height: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="regressions-display" style="position: absolute; left: 0; top: 55px; width: 100%; height: 100%">
|
||||
<div id="regressions-body">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- A modal dialog box for displaying error messages -->
|
||||
<div class="modal fade" id="error" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title alert alert-danger" id="myModalLabel">Error</h4>
|
||||
</div>
|
||||
<div class="modal-body" id="error-message">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
1
docs/benchmarks/index.json
Normal file
1
docs/benchmarks/index.json
Normal file
File diff suppressed because one or more lines are too long
4
docs/benchmarks/info.json
Normal file
4
docs/benchmarks/info.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"asv-version": "0.6.4",
|
||||
"timestamp": 1740214032970
|
||||
}
|
140
docs/benchmarks/jquery.flot.axislabels.js
Normal file
140
docs/benchmarks/jquery.flot.axislabels.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
CAxis Labels Plugin for flot. :P
|
||||
Copyright (c) 2010 Xuan Luo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
(function ($) {
|
||||
var options = { };
|
||||
|
||||
function init(plot) {
|
||||
// This is kind of a hack. There are no hooks in Flot between
|
||||
// the creation and measuring of the ticks (setTicks, measureTickLabels
|
||||
// in setupGrid() ) and the drawing of the ticks and plot box
|
||||
// (insertAxisLabels in setupGrid() ).
|
||||
//
|
||||
// Therefore, we use a trick where we run the draw routine twice:
|
||||
// the first time to get the tick measurements, so that we can change
|
||||
// them, and then have it draw it again.
|
||||
var secondPass = false;
|
||||
plot.hooks.draw.push(function (plot, ctx) {
|
||||
if (!secondPass) {
|
||||
// MEASURE AND SET OPTIONS
|
||||
$.each(plot.getAxes(), function(axisName, axis) {
|
||||
var opts = axis.options // Flot 0.7
|
||||
|| plot.getOptions()[axisName]; // Flot 0.6
|
||||
if (!opts || !opts.axisLabel)
|
||||
return;
|
||||
|
||||
var w, h;
|
||||
if (opts.axisLabelUseCanvas != false)
|
||||
opts.axisLabelUseCanvas = true;
|
||||
|
||||
if (opts.axisLabelUseCanvas) {
|
||||
// canvas text
|
||||
if (!opts.axisLabelFontSizePixels)
|
||||
opts.axisLabelFontSizePixels = 14;
|
||||
if (!opts.axisLabelFontFamily)
|
||||
opts.axisLabelFontFamily = 'sans-serif';
|
||||
// since we currently always display x as horiz.
|
||||
// and y as vertical, we only care about the height
|
||||
w = opts.axisLabelFontSizePixels;
|
||||
h = opts.axisLabelFontSizePixels;
|
||||
|
||||
} else {
|
||||
// HTML text
|
||||
var elem = $('<div class="axisLabels" style="position:absolute;">' + opts.axisLabel + '</div>');
|
||||
plot.getPlaceholder().append(elem);
|
||||
w = elem.outerWidth(true);
|
||||
h = elem.outerHeight(true);
|
||||
elem.remove();
|
||||
}
|
||||
|
||||
if (axisName.charAt(0) == 'x')
|
||||
axis.labelHeight += h;
|
||||
else
|
||||
axis.labelWidth += w;
|
||||
opts.labelHeight = axis.labelHeight;
|
||||
opts.labelWidth = axis.labelWidth;
|
||||
});
|
||||
// re-draw with new label widths and heights
|
||||
secondPass = true;
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
|
||||
} else {
|
||||
// DRAW
|
||||
$.each(plot.getAxes(), function(axisName, axis) {
|
||||
var opts = axis.options // Flot 0.7
|
||||
|| plot.getOptions()[axisName]; // Flot 0.6
|
||||
if (!opts || !opts.axisLabel)
|
||||
return;
|
||||
|
||||
if (opts.axisLabelUseCanvas) {
|
||||
// canvas text
|
||||
var ctx = plot.getCanvas().getContext('2d');
|
||||
ctx.save();
|
||||
ctx.font = opts.axisLabelFontSizePixels + 'px ' +
|
||||
opts.axisLabelFontFamily;
|
||||
var width = ctx.measureText(opts.axisLabel).width;
|
||||
var height = opts.axisLabelFontSizePixels;
|
||||
var x, y;
|
||||
if (axisName.charAt(0) == 'x') {
|
||||
x = plot.getPlotOffset().left + plot.width()/2 - width/2;
|
||||
y = plot.getCanvas().height;
|
||||
} else {
|
||||
x = height * 0.72;
|
||||
y = plot.getPlotOffset().top + plot.height()/2 - width/2;
|
||||
}
|
||||
ctx.translate(x, y);
|
||||
ctx.rotate((axisName.charAt(0) == 'x') ? 0 : -Math.PI/2);
|
||||
ctx.fillText(opts.axisLabel, 0, 0);
|
||||
ctx.restore();
|
||||
|
||||
} else {
|
||||
// HTML text
|
||||
plot.getPlaceholder().find('#' + axisName + 'Label').remove();
|
||||
var elem = $('<div id="' + axisName + 'Label" " class="axisLabels" style="position:absolute;">' + opts.axisLabel + '</div>');
|
||||
if (axisName.charAt(0) == 'x') {
|
||||
elem.css('left', plot.getPlotOffset().left + plot.width()/2 - elem.outerWidth()/2 + 'px');
|
||||
elem.css('bottom', '0px');
|
||||
} else {
|
||||
elem.css('top', plot.getPlotOffset().top + plot.height()/2 - elem.outerHeight()/2 + 'px');
|
||||
elem.css('left', '0px');
|
||||
}
|
||||
plot.getPlaceholder().append(elem);
|
||||
}
|
||||
});
|
||||
secondPass = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'axisLabels',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
44
docs/benchmarks/regressions.css
Normal file
44
docs/benchmarks/regressions.css
Normal file
|
@ -0,0 +1,44 @@
|
|||
#regressions-body {
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
#regressions-body table thead th {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#regressions-body table thead th.desc:after {
|
||||
content: ' \2191';
|
||||
}
|
||||
|
||||
#regressions-body table thead th.asc:after {
|
||||
content: ' \2193';
|
||||
}
|
||||
|
||||
#regressions-body table.ignored {
|
||||
padding-top: 1em;
|
||||
color: #ccc;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#regressions-body table.ignored a {
|
||||
color: #82abda;
|
||||
}
|
||||
|
||||
#regressions-body .feed-div {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#regressions-body table tbody td.date {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#regressions-body table button {
|
||||
margin-top: -2px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
618
docs/benchmarks/regressions.js
Normal file
618
docs/benchmarks/regressions.js
Normal file
|
@ -0,0 +1,618 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
/* Cached contents of downloaded regressions.json */
|
||||
var regression_data = null;
|
||||
/* Current page title */
|
||||
var current_title = "All regressions";
|
||||
/* Whether HTML5 local storage is available */
|
||||
var local_storage_available = false;
|
||||
/* Key prefix for ignored regressions. For each ignored regression,
|
||||
a key "ignore_key_prefix + md5(benchmark_name + date_a + date_b)"
|
||||
is added to HTML5 local storage.
|
||||
*/
|
||||
var ignore_key_prefix = null;
|
||||
/* Set of ignored regressions, same information as in HTML5 local storage.
|
||||
Useful if local storage runs out of space. */
|
||||
var ignored_regressions = {};
|
||||
/* Whether to force reload on next page update */
|
||||
var skip_reload = false;
|
||||
|
||||
function load_data(params) {
|
||||
$("#title").text(current_title);
|
||||
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
/* html5 local storage available */
|
||||
local_storage_available = true;
|
||||
}
|
||||
|
||||
if (regression_data !== null) {
|
||||
// already displayed
|
||||
if (!skip_reload) {
|
||||
var main_div = display_data(regression_data, params);
|
||||
$('#regressions-body').empty();
|
||||
$('#regressions-body').append(main_div);
|
||||
}
|
||||
skip_reload = false;
|
||||
}
|
||||
else {
|
||||
var message = $('<div>Loading...</div>');
|
||||
skip_reload = false;
|
||||
$('#regressions-body').append(message);
|
||||
$.ajax({
|
||||
url: 'regressions.json' + '?timestamp=' + $.asv.main_timestamp,
|
||||
dataType: "json",
|
||||
cache: true
|
||||
}).done(function (data) {
|
||||
regression_data = data;
|
||||
var main_div = display_data(data, params);
|
||||
$('#regressions-body').empty();
|
||||
$('#regressions-body').append(main_div);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function update_url(params, reload) {
|
||||
var info = $.asv.parse_hash_string(window.location.hash);
|
||||
$.each(params || {}, function(key, value) {
|
||||
info.params[key] = value;
|
||||
});
|
||||
|
||||
var new_hash = $.asv.format_hash_string(info);
|
||||
if (new_hash != window.location.hash) {
|
||||
if (reload === undefined) {
|
||||
skip_reload = false;
|
||||
}
|
||||
else {
|
||||
skip_reload = !reload;
|
||||
}
|
||||
window.location.hash = new_hash;
|
||||
}
|
||||
else {
|
||||
skip_reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
function display_data(data, params) {
|
||||
var main_div = $('<div/>');
|
||||
var branches = $.asv.main_json.params['branch'];
|
||||
var all_ignored_keys = {};
|
||||
|
||||
ignore_key_prefix = 'asv-r-' + $.asv.main_json.project;
|
||||
|
||||
if (branches && branches.length > 1) {
|
||||
/* Add a branch selector */
|
||||
var dropdown_menu = $('<ul class="dropdown-menu" role="menu"/>');
|
||||
var dropdown_div = $('<div class="dropdown">');
|
||||
|
||||
dropdown_div.append($('<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">Branches ' +
|
||||
'<span class="caret"/></button>'));
|
||||
dropdown_div.append(dropdown_menu);
|
||||
|
||||
main_div.append(dropdown_div);
|
||||
}
|
||||
|
||||
var feed_div = $('<div class="feed-div"><a class="btn" href="regressions.xml">Feed (Atom)</a></div>');
|
||||
main_div.append(feed_div);
|
||||
|
||||
var group_div = $('<div>');
|
||||
var group_button = $('<button class="btn btn-small"/>');
|
||||
if (params.grouped) {
|
||||
group_button.text('Ungroup regressions');
|
||||
group_button.on('click', function(evt) {
|
||||
update_url({'grouped': []});
|
||||
});
|
||||
}
|
||||
else {
|
||||
group_button.text('Group regressions');
|
||||
group_button.on('click', function(evt) {
|
||||
update_url({'grouped': ["true"]});
|
||||
});
|
||||
}
|
||||
group_div.append(group_button);
|
||||
main_div.append(group_div);
|
||||
|
||||
$.each(branches, function(i, branch) {
|
||||
var branch_div = $('<div class="regression-div"/>')
|
||||
|
||||
var display_table = $('<table class="table table-hover"/>');
|
||||
var ignored_table = $('<table class="table table-hover ignored"/>');
|
||||
var ignored_button = $('<button class="btn btn-default">Show ignored regressions...</button>');
|
||||
var ignored_conf_sample_div = $('<div class="ignored"/>');
|
||||
|
||||
if (branches && branches.length > 1) {
|
||||
var branch_link = $('<a/>')
|
||||
branch_link.text(branch);
|
||||
|
||||
dropdown_menu.append($('<li role="presentation"/>').append(branch_link));
|
||||
branch_link.on('click', function(evt) {
|
||||
current_title = "Regressions in " + branch + " branch";
|
||||
update_url({'branch': [branch]}, false);
|
||||
$("#title").text(current_title);
|
||||
$(".regression-div").hide();
|
||||
$(".ignored").hide();
|
||||
ignored_button.show();
|
||||
$("#regression-div-" + i).show();
|
||||
$("#regression-div-" + i + '-ignored').show();
|
||||
});
|
||||
}
|
||||
else {
|
||||
branch = null;
|
||||
}
|
||||
|
||||
branch_div.attr('id', 'regression-div-' + i);
|
||||
branch_div.hide();
|
||||
main_div.append(branch_div);
|
||||
|
||||
if (params.grouped) {
|
||||
create_grouped_data_table(display_table, ignored_table, ignored_conf_sample_div,
|
||||
data, params, branch, all_ignored_keys);
|
||||
}
|
||||
else {
|
||||
create_data_table(display_table, ignored_table, ignored_conf_sample_div,
|
||||
data, params, branch, all_ignored_keys);
|
||||
}
|
||||
branch_div.append(display_table);
|
||||
ignored_table.hide();
|
||||
ignored_conf_sample_div.hide();
|
||||
|
||||
branch_div.append(ignored_table);
|
||||
branch_div.append(ignored_conf_sample_div);
|
||||
|
||||
update_ignore_conf_sample(data, ignored_conf_sample_div, branch);
|
||||
|
||||
branch_div.append(ignored_button);
|
||||
ignored_button.on('click', function(evt) {
|
||||
ignored_button.hide();
|
||||
$(".ignored").show();
|
||||
});
|
||||
});
|
||||
|
||||
var branch_index = 0;
|
||||
if (branches && branches.length > 1) {
|
||||
if (params.branch) {
|
||||
branch_index = branches.indexOf(params.branch[0]);
|
||||
if (branch_index < 0) {
|
||||
branch_index = 0;
|
||||
}
|
||||
}
|
||||
current_title = "Regressions in " + branches[branch_index] + " branch";
|
||||
}
|
||||
$("#title").text(current_title);
|
||||
main_div.find("#regression-div-" + branch_index).show();
|
||||
main_div.show();
|
||||
|
||||
if (local_storage_available) {
|
||||
/* Clear out local storage space */
|
||||
var keys = Object.keys(localStorage);
|
||||
$.each(keys, function(i, key) {
|
||||
if (key.slice(0, ignore_key_prefix.length) == ignore_key_prefix &&
|
||||
!all_ignored_keys[key]) {
|
||||
delete localStorage[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return main_div;
|
||||
}
|
||||
|
||||
function create_data_table(display_table, ignored_table, ignored_conf_sample_div,
|
||||
data, params, branch, all_ignored_keys) {
|
||||
var table_head = $('<thead><tr>' +
|
||||
'<th data-sort="string">Benchmark</th>' +
|
||||
'<th data-sort="string">Date</th>' +
|
||||
'<th data-sort="string">Commit</th>' +
|
||||
'<th data-sort="factor">Factor</th>' +
|
||||
'<th data-sort="value">Before</th>' +
|
||||
'<th data-sort="value">Best after</th>' +
|
||||
'<th></th>' +
|
||||
'</tr></thead>');
|
||||
|
||||
display_table.append(table_head);
|
||||
ignored_table.append(table_head.clone());
|
||||
|
||||
var table_body = $('<tbody/>');
|
||||
var ignored_table_body = $('<tbody/>');
|
||||
|
||||
var regressions = data['regressions'];
|
||||
|
||||
$.each(regressions, function (i, item) {
|
||||
var benchmark_name = item[0];
|
||||
var graph_url = item[1];
|
||||
var param_dict = item[2];
|
||||
var parameter_idx = item[3];
|
||||
var last_value = item[4];
|
||||
var best_value = item[5];
|
||||
var jumps = item[6]; // [[rev1, rev2, before, after], ...]
|
||||
|
||||
if (jumps === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (branch !== null && param_dict['branch'] != branch) {
|
||||
return;
|
||||
}
|
||||
|
||||
var benchmark_basename = benchmark_name.replace(/\([\s\S]*/, '');
|
||||
var benchmark = $.asv.main_json.benchmarks[benchmark_basename];
|
||||
var url_params = {};
|
||||
|
||||
$.each(param_dict, function (key, value) {
|
||||
url_params[key] = [value];
|
||||
});
|
||||
|
||||
if (parameter_idx !== null) {
|
||||
$.each($.asv.param_selection_from_flat_idx(benchmark.params, parameter_idx).slice(1), function(i, param_values) {
|
||||
url_params['p-'+benchmark.param_names[i]] = [benchmark.params[i][param_values[0]]];
|
||||
});
|
||||
}
|
||||
|
||||
$.each(jumps, function(i, revs) {
|
||||
var row = $('<tr/>');
|
||||
|
||||
var commit_a = $.asv.get_commit_hash(revs[0]);
|
||||
var commit_b = $.asv.get_commit_hash(revs[1]);
|
||||
|
||||
var old_value = revs[2];
|
||||
var new_value = revs[3];
|
||||
|
||||
var factor = new_value / old_value;
|
||||
|
||||
if (commit_a) {
|
||||
url_params.commits = [commit_a + '-' + commit_b];
|
||||
}
|
||||
else {
|
||||
url_params.commits = [commit_b];
|
||||
}
|
||||
|
||||
var benchmark_url = $.asv.format_hash_string({
|
||||
location: [benchmark_basename],
|
||||
params: url_params
|
||||
});
|
||||
|
||||
new_value = $.asv.pretty_unit(new_value, benchmark.unit);
|
||||
old_value = $.asv.pretty_unit(old_value, benchmark.unit);
|
||||
|
||||
var benchmark_link = $('<a/>').attr('href', benchmark_url).text(benchmark_name);
|
||||
row.append($('<td/>').append(benchmark_link));
|
||||
|
||||
var date_fmt = new Date($.asv.main_json.revision_to_date[revs[1]]);
|
||||
row.append($('<td class="date"/>').text($.asv.format_date_yyyymmdd_hhmm(date_fmt)));
|
||||
|
||||
var commit_td = $('<td/>');
|
||||
|
||||
if (commit_a) {
|
||||
if ($.asv.main_json.show_commit_url.match(/.*\/\/github.com\//)) {
|
||||
var commit_url = ($.asv.main_json.show_commit_url + '../compare/'
|
||||
+ commit_a + '...' + commit_b);
|
||||
commit_td.append(
|
||||
$('<a/>').attr('href', commit_url).text(commit_a + '..' + commit_b));
|
||||
}
|
||||
else {
|
||||
commit_td.append($('<span/>').text(commit_a + '..' + commit_b));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var commit_url = $.asv.main_json.show_commit_url + commit_b;
|
||||
commit_td.append(
|
||||
$('<a/>').attr('href', commit_url).text(commit_b));
|
||||
}
|
||||
|
||||
row.append(commit_td);
|
||||
|
||||
row.append($('<td/>').text(factor.toFixed(2) + 'x'));
|
||||
row.append($('<td/>').text(old_value));
|
||||
row.append($('<td/>').text(new_value));
|
||||
|
||||
/* html5 local storage has limited size, so store hashes
|
||||
rather than potentially long strings */
|
||||
var ignore_key = get_ignore_key(item, revs);
|
||||
all_ignored_keys[ignore_key] = 1;
|
||||
|
||||
var is_ignored = is_key_ignored(ignore_key);
|
||||
var ignore_button = $('<button class="btn btn-small"/>');
|
||||
|
||||
row.attr('id', ignore_key);
|
||||
|
||||
ignore_button.on('click', function(evt) {
|
||||
if (is_key_ignored(ignore_key)) {
|
||||
set_key_ignore_status(ignore_key, false);
|
||||
var item = ignored_table_body.find('#' + ignore_key).detach();
|
||||
ignore_button.text('Ignore');
|
||||
table_body.append(item);
|
||||
}
|
||||
else {
|
||||
set_key_ignore_status(ignore_key, true);
|
||||
var item = table_body.find('#' + ignore_key).detach();
|
||||
ignore_button.text('Unignore');
|
||||
ignored_table_body.append(item);
|
||||
}
|
||||
update_ignore_conf_sample(data, ignored_conf_sample_div, branch);
|
||||
});
|
||||
|
||||
row.append($('<td/>').append(ignore_button));
|
||||
|
||||
if (!is_ignored) {
|
||||
ignore_button.text('Ignore');
|
||||
table_body.append(row);
|
||||
}
|
||||
else {
|
||||
ignore_button.text('Unignore');
|
||||
ignored_table_body.append(row);
|
||||
}
|
||||
|
||||
/* Show a graph as a popup */
|
||||
$.asv.ui.hover_graph(benchmark_link, graph_url, benchmark_basename, parameter_idx, [revs]);
|
||||
});
|
||||
});
|
||||
|
||||
display_table.append(table_body);
|
||||
ignored_table.append(ignored_table_body);
|
||||
|
||||
setup_sort(params, display_table);
|
||||
setup_sort(params, ignored_table);
|
||||
}
|
||||
|
||||
function create_grouped_data_table(display_table, ignored_table, ignored_conf_sample_div,
|
||||
data, params, branch, all_ignored_keys) {
|
||||
var table_head = $('<thead><tr>' +
|
||||
'<th data-sort="string">Benchmark</th>' +
|
||||
'<th data-sort="string">Last date</th>' +
|
||||
'<th data-sort="string">Commits</th>' +
|
||||
'<th data-sort="factor">Factor</th>' +
|
||||
'<th data-sort="value">Best</th>' +
|
||||
'<th data-sort="value">Current</th>' +
|
||||
'<th></th>' +
|
||||
'</tr></thead>');
|
||||
|
||||
display_table.append(table_head);
|
||||
ignored_table.append(table_head.clone());
|
||||
|
||||
var table_body = $('<tbody/>');
|
||||
var regressions = data['regressions'];
|
||||
|
||||
$.each(regressions, function (i, item) {
|
||||
var benchmark_name = item[0];
|
||||
var graph_url = item[1];
|
||||
var param_dict = item[2];
|
||||
var parameter_idx = item[3];
|
||||
var last_value = item[4];
|
||||
var best_value = item[5];
|
||||
var jumps = item[6]; // [[rev1, rev2, before, after], ...]
|
||||
|
||||
if (jumps === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (branch !== null && param_dict['branch'] != branch) {
|
||||
return;
|
||||
}
|
||||
|
||||
var benchmark_basename = benchmark_name.replace(/\(.*/, '');
|
||||
var benchmark = $.asv.main_json.benchmarks[benchmark_basename];
|
||||
var url_params = {};
|
||||
|
||||
$.each(param_dict, function (key, value) {
|
||||
url_params[key] = [value];
|
||||
});
|
||||
|
||||
if (parameter_idx !== null) {
|
||||
$.each($.asv.param_selection_from_flat_idx(benchmark.params, parameter_idx).slice(1), function(i, param_values) {
|
||||
url_params['p-'+benchmark.param_names[i]] = [benchmark.params[i][param_values[0]]];
|
||||
});
|
||||
}
|
||||
|
||||
url_params.commits = [];
|
||||
|
||||
var commit_td = $('<td/>');
|
||||
|
||||
$.each(jumps, function(i, revs) {
|
||||
var commit_a = $.asv.get_commit_hash(revs[0]);
|
||||
var commit_b = $.asv.get_commit_hash(revs[1]);
|
||||
|
||||
if (commit_a) {
|
||||
url_params.commits = url_params.commits.concat([commit_a + '-' + commit_b]);
|
||||
}
|
||||
else {
|
||||
url_params.commits = url_params.commits.concat([commit_b]);
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
commit_td.append($('<span>, </span>'));
|
||||
}
|
||||
|
||||
if (commit_a) {
|
||||
if ($.asv.main_json.show_commit_url.match(/.*\/\/github.com\//)) {
|
||||
var commit_url = ($.asv.main_json.show_commit_url + '../compare/'
|
||||
+ commit_a + '...' + commit_b);
|
||||
commit_td.append(
|
||||
$('<a/>').attr('href', commit_url).text(commit_a + '..' + commit_b));
|
||||
}
|
||||
else {
|
||||
commit_td.append($('<span/>').text(commit_a + '..' + commit_b));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var commit_url = $.asv.main_json.show_commit_url + commit_b;
|
||||
commit_td.append(
|
||||
$('<a/>').attr('href', commit_url).text(commit_b));
|
||||
}
|
||||
});
|
||||
|
||||
var row = $('<tr/>');
|
||||
|
||||
var benchmark_url = $.asv.format_hash_string({
|
||||
location: [benchmark_basename],
|
||||
params: url_params
|
||||
});
|
||||
|
||||
var benchmark_link = $('<a/>').attr('href', benchmark_url).text(benchmark_name);
|
||||
$.asv.ui.hover_graph(benchmark_link, graph_url, benchmark_basename, parameter_idx, jumps);
|
||||
row.append($('<td/>').append(benchmark_link));
|
||||
|
||||
var date_td = $('<td class="date"/>');
|
||||
var date_fmt = new Date($.asv.main_json.revision_to_date[jumps[jumps.length-1][1]]);
|
||||
date_td.text($.asv.format_date_yyyymmdd_hhmm(date_fmt));
|
||||
row.append(date_td);
|
||||
|
||||
row.append(commit_td);
|
||||
|
||||
var factor_td = $('<td/>');
|
||||
row.append(factor_td);
|
||||
var factor = last_value / best_value;
|
||||
factor_td.text(factor.toFixed(2) + 'x');
|
||||
|
||||
var best_td = $('<td/>');
|
||||
best_td.text($.asv.pretty_unit(best_value, benchmark.unit));
|
||||
row.append(best_td);
|
||||
|
||||
var last_td = $('<td/>');
|
||||
last_td.text($.asv.pretty_unit(last_value, benchmark.unit));
|
||||
row.append(last_td);
|
||||
|
||||
table_body.append(row);
|
||||
});
|
||||
|
||||
display_table.append(table_body);
|
||||
|
||||
setup_sort(params, display_table);
|
||||
}
|
||||
|
||||
function get_ignore_key(item, revs) {
|
||||
var benchmark_name = item[0];
|
||||
var ignore_payload = benchmark_name;
|
||||
|
||||
if (revs[0] === null) {
|
||||
ignore_payload = ignore_payload + ',';
|
||||
}
|
||||
else {
|
||||
ignore_payload = (ignore_payload + ','
|
||||
+ $.asv.main_json.revision_to_hash[revs[0]]);
|
||||
}
|
||||
ignore_payload = (ignore_payload + ','
|
||||
+ $.asv.main_json.revision_to_hash[revs[1]]);
|
||||
|
||||
return ignore_key_prefix + md5(ignore_payload);
|
||||
}
|
||||
|
||||
function is_key_ignored(ignore_key) {
|
||||
if (local_storage_available) {
|
||||
return (ignore_key in localStorage) || (ignore_key in ignored_regressions);
|
||||
}
|
||||
else {
|
||||
return (ignore_key in ignored_regressions);
|
||||
}
|
||||
}
|
||||
|
||||
function set_key_ignore_status(ignore_key, is_ignored) {
|
||||
if (is_ignored) {
|
||||
if (local_storage_available) {
|
||||
try {
|
||||
localStorage[ignore_key] = 1;
|
||||
} catch (err) {
|
||||
/* Out of quota -- we're just going to ignore that */
|
||||
}
|
||||
}
|
||||
ignored_regressions[ignore_key] = 1;
|
||||
}
|
||||
else {
|
||||
if (local_storage_available) {
|
||||
delete localStorage[ignore_key];
|
||||
}
|
||||
delete ignored_regressions[ignore_key];
|
||||
}
|
||||
}
|
||||
|
||||
function update_ignore_conf_sample(data, ignored_conf_sample_div, branch) {
|
||||
var regressions = data['regressions'];
|
||||
var entries = {};
|
||||
var branch_suffix = "";
|
||||
|
||||
if (branch) {
|
||||
branch_suffix = "@" + branch;
|
||||
}
|
||||
|
||||
$.each(regressions, function (i, item) {
|
||||
var param_dict = item[2];
|
||||
if (branch !== null && param_dict['branch'] != branch) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(item[6], function (i, revs) {
|
||||
var ignore_key = get_ignore_key(item, revs);
|
||||
|
||||
if (is_key_ignored(ignore_key)) {
|
||||
var benchmark_name = item[0];
|
||||
var benchmark_name_re = (benchmark_name + branch_suffix).replace(/[.?*+^$[\]\\(){}|-]/g, "\\\\$&");
|
||||
var commit = $.asv.get_commit_hash(revs[1]);
|
||||
var entry = " \"^" + benchmark_name_re + "$\": \"" + commit + "\",\n";
|
||||
entries[entry] = 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
entries = Object.keys(entries);
|
||||
entries.sort();
|
||||
|
||||
var text = "// asv.conf.json excerpt for ignoring the above permanently\n\n";
|
||||
text += " \"regressions_first_commits\": {\n";
|
||||
$.each(entries, function (i, entry) {
|
||||
text += entry;
|
||||
});
|
||||
text += " }";
|
||||
|
||||
var pre = $('<pre/>');
|
||||
pre.text(text);
|
||||
ignored_conf_sample_div.empty();
|
||||
ignored_conf_sample_div.append(pre);
|
||||
}
|
||||
|
||||
function setup_sort(params, table) {
|
||||
table.stupidtable({
|
||||
'value': function(a, b) {
|
||||
function key(s) {
|
||||
for (var k = 0; k < $.asv.time_units.length; ++k) {
|
||||
var entry = $.asv.time_units[k];
|
||||
var m = s.match('^([0-9.]+)'+entry[0]+'$');
|
||||
if (m) {
|
||||
return parseFloat(m[1]) * entry[2] * 1e-30;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return key(a) - key(b)
|
||||
},
|
||||
'factor': function(a, b) {
|
||||
return parseFloat(a.replace(/x/, '')) - parseFloat(b.replace(/x/, ''));
|
||||
}
|
||||
});
|
||||
|
||||
table.on('aftertablesort', function (event, data) {
|
||||
update_url({'sort': [data.column], 'dir': [data.direction]}, false);
|
||||
/* Update appearance */
|
||||
table.find('thead th').removeClass('asc');
|
||||
table.find('thead th').removeClass('desc');
|
||||
var th_to_sort = table.find("thead th").eq(parseInt(data.column));
|
||||
if (th_to_sort) {
|
||||
th_to_sort.addClass(data.direction);
|
||||
}
|
||||
});
|
||||
|
||||
if (params.sort && params.dir) {
|
||||
var th_to_sort = table.find("thead th").eq(parseInt(params.sort[0]));
|
||||
th_to_sort.stupidsort(params.dir[0]);
|
||||
}
|
||||
else {
|
||||
var th_to_sort = table.find("thead th").eq(3);
|
||||
th_to_sort.stupidsort("desc");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Setup display hooks
|
||||
*/
|
||||
$.asv.register_page('regressions', function(params) {
|
||||
$('#regressions-display').show()
|
||||
load_data(params);
|
||||
});
|
||||
});
|
1
docs/benchmarks/regressions.json
Normal file
1
docs/benchmarks/regressions.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"regressions": []}
|
2
docs/benchmarks/regressions.xml
Normal file
2
docs/benchmarks/regressions.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"><id>tag:django-components.asv,1970-01-01:/cddbdcca8b398afd301fbfc73cc4d51103d4e3059c0e6b938d4c467ad3d1aa25</id><author><name>Airspeed Velocity</name></author><title xml:lang="en">django-components performance regressions</title><updated>2025-02-22T08:47:12Z</updated></feed>
|
136
docs/benchmarks/summarygrid.js
Normal file
136
docs/benchmarks/summarygrid.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
var summary_loaded = false;
|
||||
|
||||
/* Callback a function when an element comes in view */
|
||||
function callback_in_view(element, func) {
|
||||
function handler(evt) {
|
||||
var visible = (
|
||||
$('#summarygrid-display').css('display') != 'none' &&
|
||||
(element.offset().top <= $(window).height() + $(window).scrollTop()) &&
|
||||
(element.offset().top + element.height() >= $(window).scrollTop()));
|
||||
if (visible) {
|
||||
func();
|
||||
$(window).off('scroll', handler);
|
||||
}
|
||||
}
|
||||
$(window).on('scroll', handler);
|
||||
}
|
||||
|
||||
function get_benchmarks_by_groups() {
|
||||
var main_json = $.asv.main_json;
|
||||
var groups = {};
|
||||
$.each(main_json.benchmarks, function(bm_name, bm) {
|
||||
var i = bm_name.indexOf('.');
|
||||
var group = bm_name.slice(0, i);
|
||||
var name = bm_name.slice(i + 1);
|
||||
if (groups[group] === undefined) {
|
||||
groups[group] = [];
|
||||
}
|
||||
groups[group].push(bm_name);
|
||||
});
|
||||
return groups;
|
||||
}
|
||||
|
||||
function benchmark_container(bm) {
|
||||
var container = $(
|
||||
'<a class="btn benchmark-container" href="#' + bm.name +
|
||||
'"/>');
|
||||
var plot_div = $(
|
||||
'<div id="summarygrid-' + bm.name + '" class="benchmark-plot"/>');
|
||||
var display_name = bm.pretty_name || bm.name.slice(bm.name.indexOf('.') + 1);
|
||||
var name = $('<div class="benchmark-text">' + display_name + '</div>');
|
||||
name.tooltip({
|
||||
title: bm.name,
|
||||
html: true,
|
||||
placement: 'top',
|
||||
container: 'body',
|
||||
animation: false
|
||||
});
|
||||
|
||||
plot_div.tooltip({
|
||||
title: bm.code,
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
animation: false
|
||||
});
|
||||
|
||||
container.append(name);
|
||||
container.append(plot_div);
|
||||
|
||||
callback_in_view(plot_div, function() {
|
||||
$.asv.load_graph_data(
|
||||
'graphs/summary/' + bm.name + '.json'
|
||||
).done(function(data) {
|
||||
var options = {
|
||||
colors: $.asv.colors,
|
||||
series: {
|
||||
lines: {
|
||||
show: true,
|
||||
lineWidth: 2
|
||||
},
|
||||
shadowSize: 0
|
||||
},
|
||||
grid: {
|
||||
borderWidth: 1,
|
||||
margin: 0,
|
||||
labelMargin: 0,
|
||||
axisMargin: 0,
|
||||
minBorderMargin: 0
|
||||
},
|
||||
xaxis: {
|
||||
ticks: [],
|
||||
},
|
||||
yaxis: {
|
||||
ticks: [],
|
||||
min: 0
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
};
|
||||
|
||||
var plot = $.plot(
|
||||
plot_div, [{data: data}], options);
|
||||
}).fail(function() {
|
||||
// TODO: Handle failure
|
||||
});
|
||||
});
|
||||
return container;
|
||||
}
|
||||
|
||||
function make_summary() {
|
||||
var summary_display = $('#summarygrid-display');
|
||||
var main_json = $.asv.main_json;
|
||||
var summary_container = $('<div/>');
|
||||
|
||||
if (summary_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(get_benchmarks_by_groups(), function(group, benchmarks) {
|
||||
var group_container = $('<div class="benchmark-group"/>')
|
||||
group_container.attr('id', 'group-' + group)
|
||||
group_container.append($('<h1>' + group + '</h1>'));
|
||||
summary_display.append(group_container);
|
||||
$.each(benchmarks, function(i, bm_name) {
|
||||
var bm = $.asv.main_json.benchmarks[bm_name];
|
||||
group_container.append(benchmark_container(bm));
|
||||
});
|
||||
});
|
||||
|
||||
summary_display.append(summary_container);
|
||||
$(window).trigger('scroll');
|
||||
|
||||
summary_loaded = true;
|
||||
}
|
||||
|
||||
$.asv.register_page('', function(params) {
|
||||
$('#summarygrid-display').show();
|
||||
$("#title").text("All benchmarks");
|
||||
$('.tooltip').remove();
|
||||
make_summary();
|
||||
});
|
||||
});
|
50
docs/benchmarks/summarylist.css
Normal file
50
docs/benchmarks/summarylist.css
Normal file
|
@ -0,0 +1,50 @@
|
|||
#summarylist-body {
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
#summarylist-body table thead th {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#summarylist-body table thead th.desc:after {
|
||||
content: ' \2191';
|
||||
}
|
||||
|
||||
#summarylist-body table thead th.asc:after {
|
||||
content: ' \2193';
|
||||
}
|
||||
|
||||
#summarylist-body table.ignored {
|
||||
padding-top: 1em;
|
||||
color: #ccc;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#summarylist-body table.ignored a {
|
||||
color: #82abda;
|
||||
}
|
||||
|
||||
#summarylist-body table tbody td.positive-change {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
#summarylist-body table tbody td.negative-change {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
#summarylist-body table tbody td.value {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#summarylist-body table tbody td.change a {
|
||||
color: black;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#summarylist-body table tbody td.change-date {
|
||||
white-space: nowrap;
|
||||
}
|
451
docs/benchmarks/summarylist.js
Normal file
451
docs/benchmarks/summarylist.js
Normal file
|
@ -0,0 +1,451 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
/* The state of the parameters in the sidebar. Dictionary mapping
|
||||
strings to values determining the "enabled" configurations. */
|
||||
var state = null;
|
||||
/* Cache of constructed tables, {data_path: table_dom_id} */
|
||||
var table_cache = {};
|
||||
var table_cache_counter = 0;
|
||||
|
||||
function setup_display(state_selection) {
|
||||
var new_state = setup_state(state_selection);
|
||||
var same_state = (state !== null);
|
||||
|
||||
/* Avoid needless UI updates, e.g., on table sort */
|
||||
|
||||
if (same_state) {
|
||||
$.each(state, function (key, value) {
|
||||
if (value != new_state[key]) {
|
||||
same_state = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!same_state) {
|
||||
state = new_state;
|
||||
replace_params_ui();
|
||||
|
||||
var filename = $.asv.graph_to_path('summary', state);
|
||||
|
||||
$("#summarylist-body table").hide();
|
||||
$("#summarylist-body .message").remove();
|
||||
|
||||
if (table_cache[filename] !== undefined) {
|
||||
$(table_cache[filename]).show();
|
||||
}
|
||||
else {
|
||||
$("#summarylist-body").append($("<p class='message'>Loading...</p>"));
|
||||
$.asv.load_graph_data(
|
||||
filename
|
||||
).done(function (data) {
|
||||
var table = construct_benchmark_table(data);
|
||||
var table_name = 'summarylist-table-' + table_cache_counter;
|
||||
++table_cache_counter;
|
||||
|
||||
table.attr('id', table_name);
|
||||
table_cache[filename] = '#' + table_name;
|
||||
$("#summarylist-body .message").remove();
|
||||
$("#summarylist-body").append(table);
|
||||
table.show()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update_state_url(key, value) {
|
||||
var info = $.asv.parse_hash_string(window.location.hash);
|
||||
var new_state = get_valid_state(state, key, value);
|
||||
|
||||
$.each($.asv.main_json.params, function(param, values) {
|
||||
if (values.length > 1) {
|
||||
info.params[param] = [new_state[param]];
|
||||
}
|
||||
else if (info.params[param]) {
|
||||
delete info.params[param];
|
||||
}
|
||||
});
|
||||
|
||||
window.location.hash = $.asv.format_hash_string(info);
|
||||
}
|
||||
|
||||
function obj_copy(obj) {
|
||||
var newobj = {};
|
||||
$.each(obj, function(key, val) {
|
||||
newobj[key] = val;
|
||||
});
|
||||
return newobj;
|
||||
}
|
||||
|
||||
function obj_diff(obj1, obj2) {
|
||||
var count = 0;
|
||||
$.each(obj1, function(key, val) {
|
||||
if (obj2[key] != val) {
|
||||
++count
|
||||
}
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
function get_valid_state(tmp_state, wanted_key, wanted_value) {
|
||||
/*
|
||||
Get an available state with wanted_key having wanted_value,
|
||||
preferably as a minor modification of tmp_state.
|
||||
*/
|
||||
var best_params = null;
|
||||
var best_diff = 1e99;
|
||||
var best_hit = false;
|
||||
|
||||
tmp_state = obj_copy(tmp_state);
|
||||
if (wanted_key !== undefined) {
|
||||
tmp_state[wanted_key] = wanted_value;
|
||||
}
|
||||
|
||||
$.each($.asv.main_json.graph_param_list, function(idx, params) {
|
||||
var diff = obj_diff(tmp_state, params);
|
||||
var hit = (wanted_key === undefined || params[wanted_key] == wanted_value);
|
||||
|
||||
if ((!best_hit && hit) || (hit == best_hit && diff < best_diff)) {
|
||||
best_params = params;
|
||||
best_diff = diff;
|
||||
best_hit = hit;
|
||||
}
|
||||
});
|
||||
|
||||
if (best_params === null) {
|
||||
best_params = $.asv.main_json.graph_param_list[0];
|
||||
}
|
||||
|
||||
return obj_copy(best_params);
|
||||
}
|
||||
|
||||
function setup_state(state_selection) {
|
||||
var index = $.asv.main_json;
|
||||
var state = {};
|
||||
|
||||
state.machine = index.params.machine;
|
||||
|
||||
$.each(index.params, function(param, values) {
|
||||
state[param] = values[0];
|
||||
});
|
||||
|
||||
if (state_selection !== null) {
|
||||
/* Select a specific generic parameter state */
|
||||
$.each(index.params, function(param, values) {
|
||||
if (state_selection[param]) {
|
||||
state[param] = state_selection[param][0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return get_valid_state(state);
|
||||
}
|
||||
|
||||
function replace_params_ui() {
|
||||
var index = $.asv.main_json;
|
||||
|
||||
var nav = $('#summarylist-navigation');
|
||||
nav.empty();
|
||||
|
||||
/* Machine selection */
|
||||
$.asv.ui.make_value_selector_panel(nav, 'machine', index.params.machine, function(i, machine, button) {
|
||||
button.text(machine);
|
||||
|
||||
button.on('click', function(evt) {
|
||||
update_state_url('machine', machine);
|
||||
});
|
||||
|
||||
if (state.machine != machine) {
|
||||
button.removeClass('active');
|
||||
}
|
||||
button.removeAttr('data-toggle');
|
||||
|
||||
/* Create tooltips for each machine */
|
||||
var details = [];
|
||||
$.each(index.machines[machine], function(key, val) {
|
||||
details.push(key + ': ' + val);
|
||||
});
|
||||
details = details.join('<br/>');
|
||||
|
||||
button.tooltip({
|
||||
title: details,
|
||||
html: true,
|
||||
placement: 'right',
|
||||
container: 'body',
|
||||
animation: false
|
||||
});
|
||||
});
|
||||
|
||||
/* Generic parameter selectors */
|
||||
$.each(index.params, function(param, values) {
|
||||
if (values.length > 1 && param != 'machine') {
|
||||
$.asv.ui.make_value_selector_panel(nav, param, values, function(i, value, button) {
|
||||
var value_display;
|
||||
if (value === null)
|
||||
value_display = '[none]';
|
||||
else if (!value)
|
||||
value_display = '[default]';
|
||||
else
|
||||
value_display = value;
|
||||
|
||||
button.text(value_display);
|
||||
|
||||
if (state[param] != value) {
|
||||
button.removeClass('active');
|
||||
}
|
||||
|
||||
button.on('click', function(evt) {
|
||||
update_state_url(param, value);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(nav).find(".btn-group").removeAttr("data-toggle");
|
||||
|
||||
$.asv.ui.reflow_value_selector_panels();
|
||||
}
|
||||
|
||||
function construct_benchmark_table(data) {
|
||||
var index = $.asv.main_json;
|
||||
|
||||
/* Form a new table */
|
||||
|
||||
var table = $('<table class="table table-hover"/>');
|
||||
|
||||
var table_head = $('<thead><tr>' +
|
||||
'<th data-sort="string">Benchmark</th>' +
|
||||
'<th data-sort="float">Value</th>' +
|
||||
'<th data-sort="float">Recent change</th>' +
|
||||
'<th data-sort="string">Changed at</th>' +
|
||||
'</tr></thead>');
|
||||
table.append(table_head);
|
||||
|
||||
var table_body = $('<tbody/>');
|
||||
|
||||
$.each(data, function(row_idx, row) {
|
||||
var tr = $('<tr/>');
|
||||
var name_td = $('<td/>');
|
||||
var name = $('<a/>');
|
||||
var benchmark_url_args = {};
|
||||
var benchmark_full_url;
|
||||
var benchmark_base_url;
|
||||
|
||||
/* Format benchmark url */
|
||||
benchmark_url_args.location = [row.name];
|
||||
benchmark_url_args.params = {};
|
||||
$.each($.asv.main_json.params, function (key, values) {
|
||||
if (values.length > 1) {
|
||||
benchmark_url_args.params[key] = [state[key]];
|
||||
}
|
||||
});
|
||||
benchmark_base_url = $.asv.format_hash_string(benchmark_url_args);
|
||||
if (row.idx !== null) {
|
||||
var benchmark = $.asv.main_json.benchmarks[row.name];
|
||||
$.each($.asv.param_selection_from_flat_idx(benchmark.params, row.idx).slice(1),
|
||||
function(i, param_values) {
|
||||
benchmark_url_args.params['p-'+benchmark.param_names[i]]
|
||||
= [benchmark.params[i][param_values[0]]];
|
||||
});
|
||||
}
|
||||
benchmark_full_url = $.asv.format_hash_string(benchmark_url_args);
|
||||
|
||||
/* Benchmark name column */
|
||||
var bm_link;
|
||||
if (row.idx === null) {
|
||||
bm_link = $('<a/>').attr('href', benchmark_base_url).text(row.pretty_name);
|
||||
name_td.append(bm_link);
|
||||
}
|
||||
else {
|
||||
var basename = row.pretty_name;
|
||||
var args = null;
|
||||
var m = row.pretty_name.match(/(.*)\(.*$/);
|
||||
if (m) {
|
||||
basename = m[1];
|
||||
args = row.pretty_name.slice(basename.length);
|
||||
}
|
||||
bm_link = $('<a/>').attr('href', benchmark_base_url).text(basename);
|
||||
name_td.append(bm_link);
|
||||
if (args) {
|
||||
var bm_idx_link;
|
||||
var graph_url;
|
||||
bm_idx_link = $('<a/>').attr('href', benchmark_full_url).text(' ' + args);
|
||||
name_td.append(bm_idx_link);
|
||||
graph_url = $.asv.graph_to_path(row.name, state);
|
||||
$.asv.ui.hover_graph(bm_idx_link, graph_url, row.name, row.idx, null);
|
||||
}
|
||||
}
|
||||
$.asv.ui.hover_summary_graph(bm_link, row.name);
|
||||
|
||||
/* Value column */
|
||||
var value_td = $('<td class="value"/>');
|
||||
if (row.last_value !== null) {
|
||||
var value, err, err_str, sort_value;
|
||||
var unit = $.asv.main_json.benchmarks[row.name].unit;
|
||||
value = $.asv.pretty_unit(row.last_value, unit);
|
||||
if (unit == "seconds") {
|
||||
sort_value = row.last_value * 1e100;
|
||||
}
|
||||
else {
|
||||
sort_value = row.last_value;
|
||||
}
|
||||
var value_span = $('<span/>').text(value);
|
||||
|
||||
err = 100*row.last_err/row.last_value;
|
||||
if (err == err) {
|
||||
err_str = " \u00b1 " + err.toFixed(0.1) + '%';
|
||||
}
|
||||
else {
|
||||
err_str = "";
|
||||
}
|
||||
value_span.attr('data-toggle', 'tooltip');
|
||||
value_span.attr('title', value + err_str);
|
||||
value_td.append(value_span);
|
||||
value_td.attr('data-sort-value', sort_value);
|
||||
}
|
||||
else {
|
||||
value_td.attr('data-sort-value', -1e99);
|
||||
}
|
||||
|
||||
/* Change percentage column */
|
||||
var change_td = $('<td class="change"/>');
|
||||
if (row.prev_value !== null) {
|
||||
var text, change_str, change = 0, sort_value = 0;
|
||||
var unit = $.asv.main_json.benchmarks[row.name].unit;
|
||||
change_str = $.asv.pretty_unit(row.last_value - row.prev_value, unit);
|
||||
if (!change_str.match(/^-/)) {
|
||||
change_str = '+' + change_str;
|
||||
}
|
||||
if (row.prev_value != 0) {
|
||||
change = 100 * (row.last_value / row.prev_value - 1);
|
||||
text = change.toFixed(1) + '% (' + change_str + ')';
|
||||
if (change > 0) {
|
||||
text = '+' + text;
|
||||
}
|
||||
sort_value = change;
|
||||
}
|
||||
else {
|
||||
text = ' (' + change_str + ')';
|
||||
}
|
||||
text = text.replace('-', '\u2212');
|
||||
|
||||
var change_commit_a = $.asv.main_json.revision_to_hash[row.change_rev[0]];
|
||||
var change_commit_b = $.asv.main_json.revision_to_hash[row.change_rev[1]];
|
||||
var change_q;
|
||||
if (change_commit_a === undefined) {
|
||||
change_q = '&commits=' + change_commit_b;
|
||||
}
|
||||
else {
|
||||
change_q = '&commits=' + change_commit_a + '-' + change_commit_b;
|
||||
}
|
||||
var change_link = $('<a/>').attr('href', benchmark_full_url + change_q).text(text);
|
||||
|
||||
graph_url = $.asv.graph_to_path(row.name, state);
|
||||
$.asv.ui.hover_graph(change_link, graph_url, row.name, row.idx, [row.change_rev]);
|
||||
|
||||
change_td.append(change_link);
|
||||
|
||||
if (change > 5) {
|
||||
change_td.addClass('positive-change');
|
||||
}
|
||||
else if (change < -5) {
|
||||
change_td.addClass('negative-change');
|
||||
}
|
||||
change_td.attr('data-sort-value', sort_value);
|
||||
}
|
||||
else {
|
||||
change_td.attr('data-sort-value', 0);
|
||||
}
|
||||
|
||||
/* Change date column */
|
||||
var changed_at_td = $('<td class="change-date"/>');
|
||||
if (row.change_rev !== null) {
|
||||
var date = new Date($.asv.main_json.revision_to_date[row.change_rev[1]]);
|
||||
var commit_1 = $.asv.get_commit_hash(row.change_rev[0]);
|
||||
var commit_2 = $.asv.get_commit_hash(row.change_rev[1]);
|
||||
var commit_a = $('<a/>');
|
||||
var span = $('<span/>');
|
||||
if (commit_1) {
|
||||
var commit_url;
|
||||
if ($.asv.main_json.show_commit_url.match(/.*\/\/github.com\//)) {
|
||||
commit_url = ($.asv.main_json.show_commit_url + '../compare/'
|
||||
+ commit_1 + '...' + commit_2);
|
||||
}
|
||||
else {
|
||||
commit_url = $.asv.main_json.show_commit_url + commit_2;
|
||||
}
|
||||
commit_a.attr('href', commit_url);
|
||||
commit_a.text(commit_1 + '...' + commit_2);
|
||||
}
|
||||
else {
|
||||
commit_a.attr('href', $.asv.main_json.show_commit_url + commit_2);
|
||||
commit_a.text(commit_2);
|
||||
}
|
||||
span.text($.asv.format_date_yyyymmdd(date) + ' ');
|
||||
span.append(commit_a);
|
||||
changed_at_td.append(span);
|
||||
}
|
||||
|
||||
tr.append(name_td);
|
||||
tr.append(value_td);
|
||||
tr.append(change_td);
|
||||
tr.append(changed_at_td);
|
||||
|
||||
table_body.append(tr);
|
||||
});
|
||||
|
||||
table_body.find('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
/* Finalize */
|
||||
table.append(table_body);
|
||||
setup_sort(table);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
function setup_sort(table) {
|
||||
var info = $.asv.parse_hash_string(window.location.hash);
|
||||
|
||||
table.stupidtable();
|
||||
|
||||
table.on('aftertablesort', function (event, data) {
|
||||
var info = $.asv.parse_hash_string(window.location.hash);
|
||||
info.params['sort'] = [data.column];
|
||||
info.params['dir'] = [data.direction];
|
||||
window.location.hash = $.asv.format_hash_string(info);
|
||||
|
||||
/* Update appearance */
|
||||
table.find('thead th').removeClass('asc');
|
||||
table.find('thead th').removeClass('desc');
|
||||
var th_to_sort = table.find("thead th").eq(parseInt(data.column));
|
||||
if (th_to_sort) {
|
||||
th_to_sort.addClass(data.direction);
|
||||
}
|
||||
});
|
||||
|
||||
if (info.params.sort && info.params.dir) {
|
||||
var th_to_sort = table.find("thead th").eq(parseInt(info.params.sort[0]));
|
||||
th_to_sort.stupidsort(info.params.dir[0]);
|
||||
}
|
||||
else {
|
||||
var th_to_sort = table.find("thead th").eq(0);
|
||||
th_to_sort.stupidsort("asc");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry point
|
||||
*/
|
||||
$.asv.register_page('summarylist', function(params) {
|
||||
var state_selection = null;
|
||||
|
||||
if (Object.keys(params).length > 0) {
|
||||
state_selection = params;
|
||||
}
|
||||
|
||||
setup_display(state_selection);
|
||||
|
||||
$('#summarylist-display').show();
|
||||
$("#title").text("List of benchmarks");
|
||||
});
|
||||
});
|
BIN
docs/benchmarks/swallow.ico
Normal file
BIN
docs/benchmarks/swallow.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/benchmarks/swallow.png
Normal file
BIN
docs/benchmarks/swallow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 893 B |
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Code of Conduct
|
||||
weight: 8
|
||||
weight: 9
|
||||
---
|
||||
|
||||
--8<-- "CODE_OF_CONDUCT.md"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: License
|
||||
weight: 9
|
||||
weight: 10
|
||||
---
|
||||
|
||||
--8<-- "LICENSE"
|
||||
|
|
8
docs/overview/performance.md
Normal file
8
docs/overview/performance.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: Performance
|
||||
weight: 8
|
||||
---
|
||||
|
||||
We track the performance of `django-components` using [ASV](https://asv.readthedocs.io/en/stable/).
|
||||
|
||||
See the [benchmarks dashboard](../../benchmarks).
|
Loading…
Add table
Add a link
Reference in a new issue