| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes" /> |
| <style> |
| html { |
| font-family: BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif; |
| -webkit-font-smoothing: antialiased; |
| background-color: #fff; |
| font-size: 16px; |
| } |
| body { |
| color: #4a4a4a; |
| margin: 8px; |
| font-size: 1em; |
| font-weight: 400; |
| } |
| header { |
| margin-bottom: 8px; |
| display: flex; |
| flex-direction: column; |
| } |
| main { |
| width: 100%; |
| display: flex; |
| flex-direction: column; |
| } |
| a { |
| color: #3273dc; |
| cursor: pointer; |
| text-decoration: none; |
| } |
| a:hover { |
| color: #000; |
| } |
| button { |
| color: #fff; |
| background-color: #3298dc; |
| border-color: transparent; |
| cursor: pointer; |
| text-align: center; |
| } |
| button:hover { |
| background-color: #2793da; |
| flex: none; |
| } |
| .spacer { |
| flex: auto; |
| } |
| .small { |
| font-size: 0.75rem; |
| } |
| footer { |
| margin-top: 16px; |
| display: flex; |
| align-items: center; |
| } |
| .header-label { |
| margin-right: 4px; |
| } |
| .benchmark-set { |
| margin: 8px 0; |
| width: 100%; |
| display: flex; |
| flex-direction: column; |
| } |
| .benchmark-title { |
| font-size: 3rem; |
| font-weight: 600; |
| word-break: break-word; |
| text-align: center; |
| } |
| .benchmark-graphs { |
| display: flex; |
| flex-direction: row; |
| justify-content: space-around; |
| align-items: center; |
| flex-wrap: wrap; |
| width: 100%; |
| } |
| .benchmark-chart { |
| max-width: 1000px; |
| } |
| </style> |
| <title>Benchmarks</title> |
| </head> |
| |
| <body> |
| <header id="header"> |
| <div class="header-item"> |
| <strong class="header-label">Last Update:</strong> |
| <span id="last-update"></span> |
| </div> |
| <div class="header-item"> |
| <strong class="header-label">Repository:</strong> |
| <a id="repository-link" rel="noopener"></a> |
| </div> |
| </header> |
| <main id="main"></main> |
| <footer> |
| <button id="dl-button">Download data as JSON</button> |
| <div class="spacer"></div> |
| <div class="small">Powered by <a rel="noopener" href="https://github.com/marketplace/actions/continuous-benchmark">github-action-benchmark</a></div> |
| </footer> |
| |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.2/dist/Chart.min.js"></script> |
| <script src="data.js"></script> |
| <script id="main-script"> |
| 'use strict'; |
| (function() { |
| // Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml |
| const toolColors = { |
| cargo: '#dea584', |
| go: '#00add8', |
| benchmarkjs: '#f1e05a', |
| benchmarkluau: '#000080', |
| pytest: '#3572a5', |
| googlecpp: '#f34b7d', |
| catch2: '#f34b7d', |
| julia: '#a270ba', |
| jmh: '#b07219', |
| benchmarkdotnet: '#178600', |
| customBiggerIsBetter: '#38ff38', |
| customSmallerIsBetter: '#ff3838', |
| _: '#333333' |
| }; |
| |
| function init() { |
| function collectBenchesPerTestCase(entries) { |
| const map = new Map(); |
| for (const entry of entries) { |
| const {commit, date, tool, benches} = entry; |
| for (const bench of benches) { |
| const result = { commit, date, tool, bench }; |
| const arr = map.get(bench.name); |
| if (arr === undefined) { |
| map.set(bench.name, [result]); |
| } else { |
| arr.push(result); |
| } |
| } |
| } |
| return map; |
| } |
| |
| const data = window.BENCHMARK_DATA; |
| |
| // Render header |
| document.getElementById('last-update').textContent = new Date(data.lastUpdate).toString(); |
| const repoLink = document.getElementById('repository-link'); |
| repoLink.href = data.repoUrl; |
| repoLink.textContent = data.repoUrl; |
| |
| // Render footer |
| document.getElementById('dl-button').onclick = () => { |
| const dataUrl = 'data:,' + JSON.stringify(data, null, 2); |
| const a = document.createElement('a'); |
| a.href = dataUrl; |
| a.download = 'benchmark_data.json'; |
| a.click(); |
| }; |
| |
| // Prepare data points for charts |
| return Object.keys(data.entries).map(name => ({ |
| name, |
| dataSet: collectBenchesPerTestCase(data.entries[name]), |
| })); |
| } |
| |
| function renderAllChars(dataSets) { |
| |
| function renderGraph(parent, name, dataset) { |
| const canvas = document.createElement('canvas'); |
| canvas.className = 'benchmark-chart'; |
| parent.appendChild(canvas); |
| |
| const color = toolColors[dataset.length > 0 ? dataset[0].tool : '_']; |
| const data = { |
| labels: dataset.map(d => d.commit.id.slice(0, 7)), |
| datasets: [ |
| { |
| label: name, |
| data: dataset.map(d => d.bench.value), |
| borderColor: color, |
| backgroundColor: color + '60', // Add alpha for #rrggbbaa |
| } |
| ], |
| }; |
| const options = { |
| scales: { |
| xAxes: [ |
| { |
| scaleLabel: { |
| display: true, |
| labelString: 'commit', |
| }, |
| } |
| ], |
| yAxes: [ |
| { |
| scaleLabel: { |
| display: true, |
| labelString: dataset.length > 0 ? dataset[0].bench.unit : '', |
| }, |
| ticks: { |
| beginAtZero: true, |
| } |
| } |
| ], |
| }, |
| tooltips: { |
| callbacks: { |
| afterTitle: items => { |
| const {index} = items[0]; |
| const data = dataset[index]; |
| return '\n' + data.commit.message + '\n\n' + data.commit.timestamp + ' committed by @' + data.commit.committer.username + '\n'; |
| }, |
| label: item => { |
| let label = item.value; |
| const { range, unit } = dataset[item.index].bench; |
| label += ' ' + unit; |
| if (range) { |
| label += ' (' + range + ')'; |
| } |
| return label; |
| }, |
| afterLabel: item => { |
| const { extra } = dataset[item.index].bench; |
| return extra ? '\n' + extra : ''; |
| } |
| } |
| }, |
| onClick: (_mouseEvent, activeElems) => { |
| if (activeElems.length === 0) { |
| return; |
| } |
| // XXX: Undocumented. How can we know the index? |
| const index = activeElems[0]._index; |
| const url = dataset[index].commit.url; |
| window.open(url, '_blank'); |
| }, |
| }; |
| |
| new Chart(canvas, { |
| type: 'line', |
| data, |
| options, |
| }); |
| } |
| |
| function renderBenchSet(name, benchSet, main) { |
| const setElem = document.createElement('div'); |
| setElem.className = 'benchmark-set'; |
| main.appendChild(setElem); |
| |
| const nameElem = document.createElement('h1'); |
| nameElem.className = 'benchmark-title'; |
| nameElem.textContent = name; |
| setElem.appendChild(nameElem); |
| |
| const graphsElem = document.createElement('div'); |
| graphsElem.className = 'benchmark-graphs'; |
| setElem.appendChild(graphsElem); |
| |
| for (const [benchName, benches] of benchSet.entries()) { |
| renderGraph(graphsElem, benchName, benches) |
| } |
| } |
| |
| const main = document.getElementById('main'); |
| for (const {name, dataSet} of dataSets) { |
| renderBenchSet(name, dataSet, main); |
| } |
| } |
| |
| renderAllChars(init()); // Start |
| })(); |
| </script> |
| </body> |
| </html> |