| <!DOCTYPE html> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Groovy Compiler Performance Dashboard</title> |
| <style> |
| :root { color-scheme: light; } |
| body { |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; |
| margin: 2em auto; |
| max-width: 1200px; |
| padding: 0 1em; |
| color: #222; |
| background: #fff; |
| } |
| h1 { font-weight: 500; margin-bottom: 0.25em; } |
| .intro { color: #444; line-height: 1.45; margin-bottom: 1.5em; max-width: 70ch; } |
| .chart-wrap { position: relative; height: 480px; margin-bottom: 1.5em; } |
| .meta { color: #666; font-size: 0.9em; margin-top: 1em; line-height: 1.5; } |
| .meta a { color: #4A8CC2; text-decoration: none; } |
| .meta a:hover { text-decoration: underline; } |
| code { background: #f5f5f7; padding: 0.05em 0.3em; border-radius: 3px; font-size: 0.92em; } |
| .empty { color: #888; font-style: italic; } |
| </style> |
| </head> |
| <body> |
| <h1>Groovy compiler performance (normalised against current)</h1> |
| <p class="intro"> |
| Each daily run compiles a fixed set of Groovy source files using <code>current</code> |
| (master) and the latest releases of Groovy 3.x, 4.x and 5.x. The <code>current</code> |
| measurement from the same run is divided by each series, so <code>current = 1.0</code> by |
| construction. Values above 1 mean that version compiles faster than current; values below |
| 1 mean it compiles slower. The trends show how current drifts relative to the released lines. |
| </p> |
| |
| <div class="chart-wrap"><canvas id="ratioChart"></canvas></div> |
| |
| <div class="meta"> |
| <div id="lastUpdate"></div> |
| <div id="latest"></div> |
| <div> |
| Raw data: <a href="data.js">data.js</a> · |
| Generated by <a href="https://github.com/benchmark-action/github-action-benchmark">github-action-benchmark</a> · |
| <a href="../../../../">Apache Groovy benchmark home</a> |
| </div> |
| </div> |
| |
| <!-- Vendored locally (see vendor/README) instead of a CDN: avoids a third-party |
| runtime dependency / supply-chain surface for the published dashboard. --> |
| <script src="vendor/chart.umd.min.js"></script> |
| <script src="vendor/chartjs-adapter-date-fns.bundle.min.js"></script> |
| <script src="data.js"></script> |
| <script> |
| (function () { |
| const SERIES = [ |
| { name: 'compile@current', label: 'current (master)', color: '#1F77B4' }, |
| { name: 'compile@groovy-5', label: 'Groovy 5.x', color: '#2CA02C' }, |
| { name: 'compile@groovy-4', label: 'Groovy 4.x', color: '#FF7F0E' }, |
| { name: 'compile@groovy-3', label: 'Groovy 3.x', color: '#D62728' }, |
| ]; |
| |
| const data = window.BENCHMARK_DATA || {}; |
| const suites = data.entries || {}; |
| const suiteName = Object.keys(suites)[0]; |
| if (!suiteName) { |
| document.querySelector('.chart-wrap').innerHTML = |
| '<p class="empty">No benchmark data yet — waiting for the first <code>perf-daily</code> run.</p>'; |
| return; |
| } |
| const runs = suites[suiteName] || []; |
| |
| const datasets = SERIES.map(s => ({ |
| label: s.label, |
| borderColor: s.color, |
| backgroundColor: s.color, |
| pointRadius: 2, |
| pointHoverRadius: 5, |
| borderWidth: 2, |
| tension: 0.15, |
| spanGaps: true, |
| data: [], |
| })); |
| |
| const latestVersions = {}; |
| for (const run of runs) { |
| const byName = {}; |
| for (const b of (run.benches || [])) byName[b.name] = b; |
| const current = byName['compile@current']; |
| if (!current || !current.value) continue; |
| const x = new Date(run.date || (run.commit && run.commit.timestamp) || 0); |
| SERIES.forEach((s, idx) => { |
| const b = byName[s.name]; |
| if (!b || !b.value) return; |
| if (b.extra) latestVersions[s.name] = b.extra; |
| datasets[idx].data.push({ |
| x, |
| y: current.value / b.value, |
| absMs: b.value, |
| range: b.range || '', |
| commit: (run.commit && run.commit.id) ? run.commit.id.slice(0, 7) : '', |
| commitUrl: run.commit && run.commit.url, |
| version: b.extra || '', |
| }); |
| }); |
| } |
| |
| const baselineLine = { |
| id: 'baselineLine', |
| afterDatasetsDraw(chart) { |
| const { ctx, chartArea: { left, right }, scales: { y } } = chart; |
| const yPx = y.getPixelForValue(1); |
| ctx.save(); |
| ctx.strokeStyle = 'rgba(0,0,0,0.35)'; |
| ctx.setLineDash([4, 4]); |
| ctx.lineWidth = 1; |
| ctx.beginPath(); |
| ctx.moveTo(left, yPx); |
| ctx.lineTo(right, yPx); |
| ctx.stroke(); |
| ctx.restore(); |
| } |
| }; |
| |
| const ctx = document.getElementById('ratioChart').getContext('2d'); |
| new Chart(ctx, { |
| type: 'line', |
| data: { datasets }, |
| plugins: [baselineLine], |
| options: { |
| responsive: true, |
| maintainAspectRatio: false, |
| interaction: { mode: 'index', intersect: false }, |
| scales: { |
| x: { |
| type: 'time', |
| time: { unit: 'day', tooltipFormat: 'yyyy-MM-dd' }, |
| title: { display: true, text: 'Run date' }, |
| }, |
| y: { |
| title: { display: true, text: 'speed relative to current (higher = faster)' }, |
| grid: { color: 'rgba(0,0,0,0.06)' }, |
| }, |
| }, |
| plugins: { |
| legend: { position: 'top' }, |
| tooltip: { |
| callbacks: { |
| title(items) { |
| const r = items[0] && items[0].raw; |
| const d = new Date(items[0].parsed.x).toISOString().slice(0, 10); |
| return r && r.commit ? r.commit + ' ' + d : d; |
| }, |
| label(item) { |
| const r = item.raw; |
| const ratio = item.parsed.y.toFixed(3); |
| const abs = r.absMs ? r.absMs.toFixed(1) + ' ms' : ''; |
| const rng = r.range ? ' ' + r.range : ''; |
| const ver = r.version ? ' [' + r.version + ']' : ''; |
| return item.dataset.label + ': ' + ratio + ' x (' + abs + rng + ')' + ver; |
| }, |
| }, |
| }, |
| }, |
| }, |
| }); |
| |
| if (data.lastUpdate) { |
| document.getElementById('lastUpdate').textContent = |
| 'Last update: ' + new Date(data.lastUpdate).toISOString().replace('T', ' ').slice(0, 19) + ' UTC'; |
| } |
| const pieces = SERIES |
| .filter(s => latestVersions[s.name]) |
| .map(s => s.label + ': ' + latestVersions[s.name]); |
| if (pieces.length) { |
| document.getElementById('latest').textContent = 'Latest versions in chart: ' + pieces.join(' | '); |
| } |
| })(); |
| </script> |
| </body> |
| </html> |