1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <title>bench-flame-diff</title> 5 <link rel="preconnect" href="https://fonts.googleapis.com"> 6 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 7 <link href="https://fonts.googleapis.com/css2?family=Roboto:300,300italic,700,700italic&display=swap" rel="stylesheet"> 8 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha512-NhSC1YmyruXifcj/KFRWoC561YpHpc5Jtzgvbuzx5VozKpWvQ+4nXhPdFgmx8xqexRcpAglTj9sIBWINXa8x5w==" crossorigin="anonymous" referrerpolicy="no-referrer"/> 9 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.min.css" integrity="sha512-xiunq9hpKsIcz42zt0o2vCo34xV0j6Ny8hgEylN3XBglZDtTZ2nwnqF/Z/TTCc18sGdvCjbFInNd++6q3J0N6g==" crossorigin="anonymous" referrerpolicy="no-referrer"/> 10 <style> 11 #row--title-and-help { 12 display: flex; 13 justify-content: space-between; 14 align-items: center; 15 } 16 #row--before-after { 17 display: flex; 18 } 19 #row--before-after > div, #row--before-after > div > div { 20 display: flex; 21 flex-direction: column; 22 } 23 #row--before-after > div { 24 align-items: flex-start; 25 flex-basis: 50%; 26 padding: 5px; 27 } 28 #row--before-after > :first-child { 29 align-items: flex-end; 30 } 31 #row--before-after, #row--graphs { 32 max-width: 1800px; 33 } 34 </style> 35</head> 36<body> 37<!--title and the help button--> 38<header> 39 <div id="row--title-and-help"> 40 <h2>bench-flame-diff</h2> 41 <button onclick="window.open('http://go/bench-flame-diff-readme')">help</button> 42 </div> 43</header> 44<main> 45 <!--two column view--> 46 <div id="row--before-after"> 47 <!--column-left--> 48 <div> 49 <h3>Before</h3> 50 <div> 51 <button onclick="openTab('%before_raw_name%')">%before_raw_name%</button> 52 <button onclick="openTab('%before_diff_name%')">%before_diff_name%</button> 53 </div> 54 <div id="results-before"></div> 55 </div> 56 <!--column-right--> 57 <div> 58 <h3>After</h3> 59 <div> 60 <button onclick="openTab('%after_raw_name%')">%after_raw_name%</button> 61 <button onclick="openTab('%after_diff_name%')">%after_diff_name%</button> 62 </div> 63 <div id="results-after"></div> 64 </div> 65 </div> 66 67 <!--graphs--> 68 <div id="row--graphs"> 69 <div id="%before_raw_name%" class="svg"> 70 <object type="image/svg+xml" data="%before_raw_file%">Failed to display the file: %before_raw_file%</object> 71 </div> 72 <div id="%before_diff_name%" class="svg"> 73 <object type="image/svg+xml" data="%before_diff_file%">Failed to display the file: %before_diff_file%</object> 74 </div> 75 <div id="%after_raw_name%" class="svg"> 76 <object type="image/svg+xml" data="%after_raw_file%">Failed to display the file: %after_raw_file%</object> 77 </div> 78 <div id="%after_diff_name%" class="svg"> 79 <object type="image/svg+xml" data="%after_diff_file%">Failed to display the file: %after_diff_file%</object> 80 </div> 81 </div> 82</main> 83 84<!-- Note: 'application/json' ensures the content is treated as data (i.e. not executed) --> 85<script type="application/json" id="result-before-raw"> 86 %benchmark_result_before_raw% 87</script> 88 89<script type="application/json" id="result-after-raw"> 90 %benchmark_result_after_raw% 91</script> 92 93<script> 94 function openTab(tabName) { 95 let tab = document.getElementsByClassName("svg"); 96 for (let i = 0; i < tab.length; i++) tab[i].style.display = "none"; 97 document.getElementById(tabName).style.display = "block"; 98 } 99 100 function formatNumber(numberRaw) { 101 const intAbs = Math.abs(Math.round(numberRaw)) 102 let maxFrac = 2; 103 if (intAbs >= 10) maxFrac = 1; 104 if (intAbs >= 100) maxFrac = 0; 105 const formatter = new Intl.NumberFormat('en-US', { 106 maximumFractionDigits: maxFrac, 107 minimumFractionDigits: 0, 108 useGrouping: true, 109 }); 110 return formatter.format(numberRaw); 111 } 112 113 function populateBenchmarkResult(label, dataSourceId, traceFileName) { 114 const dataString = document.getElementById(dataSourceId).textContent.trim() 115 if (!dataString) return // no benchmark result data 116 117 const benchmark = JSON.parse(dataString).benchmarks.find(b => 118 b.profilerOutputs && 119 b.profilerOutputs.some(po => po.filename === traceFileName) 120 ) || undefined; 121 if (!benchmark || !benchmark.metrics) return // no benchmark matching the trace file name 122 const metrics = benchmark.metrics; 123 if (Object.keys(metrics).length === 0) return 124 125 let rowData = ""; 126 Object.entries(metrics).forEach(([metricName, metricResult],) => { 127 const {minimum, median, maximum} = metricResult; 128 rowData += "<tr>" + 129 `<td>${metricName}</td>` + 130 `<td>${formatNumber(minimum)}</td>` + 131 `<td>${formatNumber(median)}</td>` + 132 `<td>${formatNumber(maximum)}</td>` + 133 "</tr>" 134 }) 135 document.querySelector(`#results-${label}`).innerHTML += "<table>" + 136 "<thead>" + 137 "<th>metric</th>" + 138 "<th>min</th>" + 139 "<th>median</th>" + 140 "<th>max</th>" + 141 "</thead>" + 142 "<tbody>" + 143 rowData + 144 "</tbody>" + 145 "</table>" 146 } 147 148 populateBenchmarkResult("before", "result-before-raw", "%before_trace_file_name%") 149 populateBenchmarkResult("after", "result-after-raw", "%after_trace_file_name%") 150 openTab("%after_diff_name%"); 151</script> 152</body> 153</html> 154