<!--
Copyright 2022 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->

<!DOCTYPE html>
<html lang="en">
<head>
	<title>Go Performance Dashboard</title>
	<link rel="icon" href="https://go.dev/favicon.ico"/>
	<link rel="stylesheet" href="./static/style.css"/>
	<script src="https://ajax.googleapis.com/ajax/libs/d3js/7.4.2/d3.min.js"></script>
	<script src="./third_party/bandchart/bandchart.js"></script>
	<script src="./static/range.js"></script>
</head>

<body class="Dashboard">
<header class="Dashboard-topbar">
	<h1>
		<a href="https://farmer.golang.org/">Go Build Coordinator</a>
	</h1>
	<nav>
		<ul>
			<li><a href="https://build.golang.org/">Build Dashboard</a></li>
			<li><a href="/dashboard">Performance Dashboard</a></li>
			<li><a href="https://farmer.golang.org/builders">Builders</a></li>
		</ul>
	</nav>
</header>

<nav class="Dashboard-controls">
	<form autocomplete="off" action="./">
		<ul>
			<li>
				<div class="Dashboard-search-benchmark">
					<input id="benchmark-input" type="text" name="benchmark" placeholder="Type benchmark name..." />
				</div>
				<div class="Dashboard-search-unit">
					<input id="unit-input" type="text" name="unit" placeholder="Unit (optional)" />
				</div>
				<input type="submit" />
			</li>
			<li><a href="?benchmark=all">All benchmarks</a></li>
			<li><a href="?benchmark=regressions">Regressions first</a></li>
			<span class="left-separator"></span>
			<li>
				Repository:
				<select id="repository-select" name="repository">
					<option>go</option>
					<option>tools</option>
				</select>
				Branch:
				<select id="branch-select" name="branch">
					<option>master</option>
					<option>release-branch.go1.17</option>
					<option>release-branch.go1.18</option>
					<option>release-branch.go1.19</option>
					<option>release-branch.go1.20</option>
				</select>
				Duration (days):
				<div class="Dashboard-duration">
					<input id="days-input" type="number" name="days" value="30" />
				</div>
				End (UTC): <input id="end-input" type="datetime-local" name="end" />
				<input type="submit">
			</li>
		</ul>
	</form>
</nav>

<div class="Dashboard-documentation">
	<p>
		Each graph displays benchmark results relative to its baseline
		commit, which is the latest stable release (e.g., 1.18.3) at
		the time of testing. The 95% confidence interval is displayed
		in light gray. On hover, the graph displays the benchmarked
		commit at that point (click to view full commit).
	</p>
	<p>
		Note that some commits are not tested, so there could be
		multiple commits (not shown) between two points on the graph.
		See the <code>linux-amd64-perf</code> column on the
		<a href="https://build.golang.org/?repo=golang.org%2fx%2fbenchmarks">x/benchmarks build dashboard</a>
		for tested ("ok") / untested (empty) commits.
	</p>
	<p>
		The 'branch' selection above is the Go branch that benchmarking
		ran against on <a href=https://build.golang.org>the build dashboard</a>,
		not the subrepo branch.
	</p>
	<p>
		Using the 'unit' search box above leads to a page that shows much
		more detail about each individual point in the selected time range.
		Another way of reaching this page is to click the unit name that acts
		as each graph's title, i.e. "sec/op".
	</p>
</div>

<grid id="dashboard">
	<grid id="loading" class="Dashboard-section Dashboard-section-expand">
		<h2 class="Dashboard-title" id="loading">Loading...</h2>
	</grid>
</grid>

<script>
// minViewPercentDelta represents the minimum range we're willing to
// let the Y axis have for charts and X axis for ranges in the per-unit
// view. In both cases the unit of this value is a delta percent, hence
// the name.
//
// This constant exists because allowing the axis' range to be arbitrarily
// small produces results that are really noisy visually, even though they
// represent virtually no change. For instance, a relatively low-noise
// series of benchmark results, with a min delta of -0.05% and and +0.05%
// might appear really noisy if we "zoom" in too far, when in actuality
// the amount of noise is incredibly low.
const minViewDeltaPercent = 0.025;

function removeLoadingMessage() {
	let loading = document.getElementById("loading");
	loading.parentNode.removeChild(loading);
}

function addCharts(benchmarks) {
	let dashboard = document.getElementById("dashboard");

	removeLoadingMessage();

	let prevName = "";
	let grid = null;
	for (const b in benchmarks) {
		const bench = benchmarks[b];

		if (bench.Name != prevName) {
			prevName = bench.Name;

			let section = document.createElement("grid");
			section.classList.add("Dashboard-section");
			dashboard.appendChild(section);

			let link = document.createElement("a");
			link.href = "?benchmark=" + bench.Name;
			link.textContent = bench.Name;

			let title = document.createElement("h2");
			title.classList.add("Dashboard-title");
			title.appendChild(link);
			section.appendChild(title);

			grid = document.createElement("grid");
			grid.classList.add("Dashboard-grid");
			section.appendChild(grid);
		}

		let item = document.createElement("div");
		item.classList.add("Dashboard-grid-item");
		item.appendChild(BandChart(bench.Values, {
			benchmark: bench.Name,
			unit: bench.Unit,
			minViewDeltaPercent: minViewDeltaPercent,
		}));
		grid.appendChild(item);
	}
}

function addTable(bench, unit) {
	let dashboard = document.getElementById("dashboard");

	removeLoadingMessage();

	let section = document.createElement("grid");
	section.classList.add("Dashboard-section");
	section.classList.add("Dashboard-section-expand");
	dashboard.appendChild(section);

	let link = document.createElement("a");
	link.href = "?benchmark=" + bench.Name + "&unit=" + unit;
	link.textContent = bench.Name + " (" + unit + ")";

	let title = document.createElement("h2");
	title.classList.add("Dashboard-title");
	title.appendChild(link);
	section.appendChild(title);

	const table = document.createElement("table");
	table.classList.add("Dashboard-table");
	section.appendChild(table);

	const createCell = function(text, header) {
		let elemType = "td";
		if (header) {
			elemType = "th";
		}
		const elem = document.createElement(elemType);
		elem.textContent = text;
		return elem;
	}

	// Create the header.
	const header = document.createElement("tr");
	header.appendChild(createCell("Date", true));
	header.appendChild(createCell("Commit", true));
	header.appendChild(createCell("Delta", true));
	table.appendChild(header);

	// Find the min and max.
	let min = bench.Values[0].Low;
	let max = bench.Values[0].High;
	for (let i = 1; i < bench.Values.length; i++) {
		if (bench.Values[i].Low < min) {
			min = bench.Values[i].Low;
		}
		if (bench.Values[i].High > max) {
			max = bench.Values[i].High;
		}
	}

	// Clamp for presentation.
	if (min < 0 && min > -minViewDeltaPercent) {
		min = -minViewDeltaPercent
	}
	if (max > 0 && max < minViewDeltaPercent) {
		max = minViewDeltaPercent
	}
	if (max-min < 2*minViewDeltaPercent) {
		const amt = (2*minViewDeltaPercent-(max-min))/2;
		max += amt;
		min -= amt;
	}

	// Iterate backwards, showing the most recent first.
	for (let i = bench.Values.length-1; i >= 0; i--) {
		const v = bench.Values[i];

		// Create a row per value.
		const row = document.createElement("tr");

		// Commit date.
		row.appendChild(createCell(Intl.DateTimeFormat([], {
			dateStyle: "long",
			timeStyle: "short",
		}).format(v.CommitDate), false));

		// Commit hash.
		const commitHash = createCell("", false);
		const commitLink = document.createElement("a");
		commitLink.href = "https://go.googlesource.com/go/+show/" + v.CommitHash;
		commitLink.textContent = v.CommitHash.slice(0, 7);
		commitHash.appendChild(commitLink);
		commitHash.classList.add("Dashboard-table-commit")
		row.appendChild(commitHash);

		// Range visualization.
		const range = createCell("", false);
		range.appendChild(Range(v.Low, v.Center, v.High, min, max, 640, 32, bench.Unit));
		range.classList.add("Dashboard-table-range")
		row.appendChild(range);

		table.appendChild(row);
	}
}

function failure(name, response) {
	let dashboard = document.getElementById("dashboard");

	removeLoadingMessage();

	let title = document.createElement("h2");
	title.classList.add("Dashboard-title");
	title.textContent = "Benchmark \"" + name + "\" not found.";
	dashboard.appendChild(title);

	let message = document.createElement("p");
	message.classList.add("Dashboard-documentation");
	response.text().then(function(error) {
		message.textContent = error;
	});
	dashboard.appendChild(message);
}

// Fill search boxes from query params.
function prefillSearch() {
	let params = new URLSearchParams(window.location.search);

	let benchmark = params.get('benchmark');
	if (benchmark) {
		let input = document.getElementById('benchmark-input');
		input.value = benchmark;
	}

	let unit = params.get('unit');
	if (unit) {
		let input = document.getElementById('unit-input');
		input.value = unit;
	}

	let repository = params.get('repository');
	if (repository) {
		let select = document.getElementById('repository-select');
		select.value = repository;
	}

	let branch = params.get('branch');
	if (branch) {
		let select = document.getElementById('branch-select');
		select.value = branch;
	}

	let days = params.get('days');
	if (days) {
		let input = document.getElementById('days-input');
		input.value = days;
	}

	let end = params.get('end');
	let input = document.getElementById('end-input');
	if (end) {
		input.value = end;
	} else {
		// Default to now.
		let now = new Date();

		// toISOString always uses UTC, then we just chop off the end
		// of string to get the datetime-local format of
		// 2000-12-31T15:00.
		//
		// Yes, this is really the suggested approach...
		input.value = now.toISOString().slice(0, 16);
	}
}
prefillSearch()

// Fetch content.
let benchmark = (new URLSearchParams(window.location.search)).get('benchmark');
let unit = (new URLSearchParams(window.location.search)).get('unit');
let dataURL = './data.json' + window.location.search;  // Pass through all URL params.
fetch(dataURL)
	.then(response => {
		if (!response.ok) {
			failure(benchmark, response);
			throw new Error("Data fetch failed");
		}
		return response.json();
	})
	.then(function(benchmarks) {
		// Convert CommitDate to a proper date.
		benchmarks.forEach(function(b) {
			b.Values.forEach(function(v) {
				v.CommitDate = new Date(v.CommitDate);
			});
		});

		// If we have an explicit unit, then there should be just one result.
		if (unit) {
			if (benchmarks.length !== 1) {
				failure(benchmark, "got more that one benchmark when a unit was specified");
				throw new Error("Data fetch failed");
			}
			addTable(benchmarks[0], unit);
		} else {
			addCharts(benchmarks);
		}
	});
</script>

</body>
</html>
