'));
+ dropdown_div.append(dropdown_menu);
+
+ main_div.append(dropdown_div);
+ }
+
+ var feed_div = $('
');
+ var group_button = $('
');
+ 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 = $('
')
+
+ var display_table = $('
');
+ var ignored_table = $('
');
+ var ignored_button = $('
Show ignored regressions... ');
+ var ignored_conf_sample_div = $('
');
+
+ if (branches && branches.length > 1) {
+ var branch_link = $('
')
+ branch_link.text(branch);
+
+ dropdown_menu.append($('
').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 = $('
' +
+ 'Benchmark ' +
+ 'Date ' +
+ 'Commit ' +
+ 'Factor ' +
+ 'Before ' +
+ 'Best after ' +
+ ' ' +
+ ' ');
+
+ display_table.append(table_head);
+ ignored_table.append(table_head.clone());
+
+ var table_body = $('
');
+ var ignored_table_body = $('
');
+
+ 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 = $('
');
+
+ 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 = $('
').attr('href', benchmark_url).text(benchmark_name);
+ row.append($('
').append(benchmark_link));
+
+ var date_fmt = new Date($.asv.main_json.revision_to_date[revs[1]]);
+ row.append($('
').text($.asv.format_date_yyyymmdd_hhmm(date_fmt)));
+
+ var commit_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(
+ $('
').attr('href', commit_url).text(commit_a + '..' + commit_b));
+ }
+ else {
+ commit_td.append($('
').text(commit_a + '..' + commit_b));
+ }
+ }
+ else {
+ var commit_url = $.asv.main_json.show_commit_url + commit_b;
+ commit_td.append(
+ $('
').attr('href', commit_url).text(commit_b));
+ }
+
+ row.append(commit_td);
+
+ row.append($('
').text(factor.toFixed(2) + 'x'));
+ row.append($('
').text(old_value));
+ row.append($('
').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 = $('
');
+
+ 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($('
').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 = $('
' +
+ 'Benchmark ' +
+ 'Last date ' +
+ 'Commits ' +
+ 'Factor ' +
+ 'Best ' +
+ 'Current ' +
+ ' ' +
+ ' ');
+
+ display_table.append(table_head);
+ ignored_table.append(table_head.clone());
+
+ var table_body = $('
');
+ 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 = $('
');
+
+ $.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($('
, '));
+ }
+
+ 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(
+ $('
').attr('href', commit_url).text(commit_a + '..' + commit_b));
+ }
+ else {
+ commit_td.append($('
').text(commit_a + '..' + commit_b));
+ }
+ }
+ else {
+ var commit_url = $.asv.main_json.show_commit_url + commit_b;
+ commit_td.append(
+ $('
').attr('href', commit_url).text(commit_b));
+ }
+ });
+
+ var row = $('
');
+
+ var benchmark_url = $.asv.format_hash_string({
+ location: [benchmark_basename],
+ params: url_params
+ });
+
+ var benchmark_link = $('
').attr('href', benchmark_url).text(benchmark_name);
+ $.asv.ui.hover_graph(benchmark_link, graph_url, benchmark_basename, parameter_idx, jumps);
+ row.append($('
').append(benchmark_link));
+
+ var date_td = $('
');
+ 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 = $('
');
+ row.append(factor_td);
+ var factor = last_value / best_value;
+ factor_td.text(factor.toFixed(2) + 'x');
+
+ var best_td = $('
');
+ best_td.text($.asv.pretty_unit(best_value, benchmark.unit));
+ row.append(best_td);
+
+ var last_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.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);
+ });
+});
diff --git a/regressions.json b/regressions.json
new file mode 100644
index 000000000..37090c9e5
--- /dev/null
+++ b/regressions.json
@@ -0,0 +1 @@
+{"regressions": []}
\ No newline at end of file
diff --git a/regressions.xml b/regressions.xml
new file mode 100644
index 000000000..6a9cd1321
--- /dev/null
+++ b/regressions.xml
@@ -0,0 +1,2 @@
+
+
tag:pyglotaran.asv,1970-01-01:/e3afdb036d07bdffe10d4750b1c583fedb68acec65742bc66966d904392350e1 Airspeed Velocity pyglotaran performance regressions 2024-07-12T11:43:27Z
\ No newline at end of file
diff --git a/summarygrid.js b/summarygrid.js
new file mode 100644
index 000000000..b32747f3e
--- /dev/null
+++ b/summarygrid.js
@@ -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 = $(
+ '
');
+ var plot_div = $(
+ '
');
+ var display_name = bm.pretty_name || bm.name.slice(bm.name.indexOf('.') + 1);
+ var name = $('
' + display_name + '
');
+ 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 = $('
');
+
+ if (summary_loaded) {
+ return;
+ }
+
+ $.each(get_benchmarks_by_groups(), function(group, benchmarks) {
+ var group_container = $('
')
+ group_container.attr('id', 'group-' + group)
+ group_container.append($('
' + group + ' '));
+ 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();
+ });
+});
diff --git a/summarylist.css b/summarylist.css
new file mode 100644
index 000000000..938543367
--- /dev/null
+++ b/summarylist.css
@@ -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;
+}
diff --git a/summarylist.js b/summarylist.js
new file mode 100644
index 000000000..e5f9e13c4
--- /dev/null
+++ b/summarylist.js
@@ -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($("
Loading...
"));
+ $.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('
');
+
+ 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 = $('
');
+
+ var table_head = $('
' +
+ 'Benchmark ' +
+ 'Value ' +
+ 'Recent change ' +
+ 'Changed at ' +
+ ' ');
+ table.append(table_head);
+
+ var table_body = $('
');
+
+ $.each(data, function(row_idx, row) {
+ var tr = $('
');
+ var name_td = $('
');
+ var name = $('
');
+ 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 = $('
').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 = $('
').attr('href', benchmark_base_url).text(basename);
+ name_td.append(bm_link);
+ if (args) {
+ var bm_idx_link;
+ var graph_url;
+ bm_idx_link = $('
').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 = $('
');
+ 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 = $('
').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 = $('
');
+ 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 = $('
').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 = $('
');
+ 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 = $('
');
+ var 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");
+ });
+});
diff --git a/swallow.ico b/swallow.ico
new file mode 100644
index 000000000..b5fcc02ba
Binary files /dev/null and b/swallow.ico differ
diff --git a/swallow.png b/swallow.png
new file mode 100644
index 000000000..552286782
Binary files /dev/null and b/swallow.png differ