diff --git a/JetStream.css b/JetStream.css index c04d205f..7bd22dd3 100644 --- a/JetStream.css +++ b/JetStream.css @@ -23,7 +23,25 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -html { +:root { + --color-primary: #34AADC; + --color-secondary: #86D9FF; + --text-color-inverse: white; + --text-color-primary: black; + --text-color-secondary: #555555; + --text-color-tertiary: #444444; + --text-color-subtle: #6c6c71; + --text-color-very-subtle: #8E8E93; + --heading-color: #2C98D1; + --link-hover-color: #0086BF; + --button-color-primary: rgb(52,170,220); + --error-text-color: #d24a59; + --benchmark-heading-color: rgb(183, 183, 183); + --benchmark-error-text-color: #ff8686; + --benchmark-done-result-color: #4A4A4A; +} + +html, svg text { font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif; font-size: 62.5%; font-synthesis: none; @@ -42,8 +60,8 @@ body { } ::selection { - background-color: #34AADC; - color: white; + background-color: var(--color-primary); + color: var(--text-color-inverse); } main { @@ -126,13 +144,13 @@ article, .summary { } h1 { - color: black; + color: var(--text-color-primary); text-align: center; } h2, h3, h4, h5, h6 { - color: #2C98D1; + color: var(--heading-color); text-align: left; } @@ -143,7 +161,7 @@ h4, h5, h6 { p { text-align: left; - color: #555555; + color: var(--text-color-secondary); margin: 0 0 3rem 0; } @@ -152,7 +170,7 @@ h5, h6 { } h6 { - color: #444444; + color: var(--text-color-tertiary); } dt { @@ -169,12 +187,12 @@ dd { a:link, a:visited { - color: #34AADC; + color: var(--color-primary); } a:hover, a:active { - color: #0086BF; + color: var(--link-hover-color); } #status { @@ -187,10 +205,10 @@ a.button { font-weight: 500; text-decoration: none; font-size: 2rem; - background-color: rgb(52,170,220); - background-image: linear-gradient(180deg, rgba(134,217,255,1) -80%, rgba(52,170,220,1) 100%); - color: rgb(255,255,255); - border: 1px solid rgb(52,170,220); + background-color: var(--button-color-primary); + background-image: linear-gradient(180deg, rgba(134,217,255,1) -80%, rgb(52,170,220) 100%); + color: var(--text-color-inverse); + border: 1px solid var(--button-color-primary); border-radius: 2px; padding: 0.3rem 9rem 0.5rem; -webkit-touch-callout: none; @@ -238,7 +256,7 @@ a.button { } .error h2, .error p { - color: #d24a59; + color: var(--error-text-color); margin-bottom: 0; text-align: center; font-weight: 500; @@ -259,17 +277,22 @@ a.button { } #result-summary label { - color: #6c6c71; + color: var(--text-color-subtle); } #result-summary .score { font-weight: bold; font-size: 4rem; line-height: 1; - color: #34AADC; + color: var(--color-primary); font-weight: 500; } +.benchmark .plot svg { + display: inline-block; + vertical-align: middle; +} + #result-summary .score .interval { display: block; font-weight: normal; @@ -289,30 +312,30 @@ a.button { max-width: 20%; min-width: 200px; text-align: left; - color: #8E8E93; + color: var(--text-color-very-subtle); font-size: 1.6rem; margin: 0 1.6rem 3rem 0; } -.benchmark h4, .benchmark .result, .benchmark label { +.benchmark h4, .benchmark .result, .benchmark label, .benchmark .plot { color: transparent; background: linear-gradient(160deg, rgba(249,249,249,1) 0%, rgba(238,238,238,1) 100%); border-radius: 3px; } .benchmark h3 { - color: rgb(183, 183, 183); + color: var(--benchmark-heading-color); } -.benchmark-running h4, .benchmark-running .result, .benchmark-running label { - color: #86D9FF; - background-color: #86D9FF; +.benchmark-running h4, .benchmark-running .result, .benchmark-running label, .benchmark-running .plot { + color: var(--color-secondary); + background-color: var(--color-secondary); background-image: none; } -.benchmark-done h3, .benchmark-done h4, .benchmark-done .result, .benchmark-done label { +.benchmark-done h3, .benchmark-done h4, .benchmark-done .result, .benchmark-done label, .benchmark-done .plot { background-color: transparent; background-image: none; -webkit-touch-callout: revert; @@ -322,14 +345,14 @@ a.button { user-select: text; } -.benchmark-error h4, .benchmark-error .result, .benchmark-error label { - color: #ff8686; - background-color: #ff8686; +.benchmark-error h4, .benchmark-error .result, .benchmark-error label, .benchmark-error .plot { + color: var(--benchmark-error-text-color); + background-color: var(--benchmark-error-text-color); background-image: none; } .benchmark-error h3 { - color: #ff8686; + color: var(--benchmark-error-text-color); } .benchmark h3 { @@ -341,11 +364,11 @@ a.button { .benchmark-running h3 { background-color: transparent; background-image: none; - color: #34AADC; + color: var(--color-primary); } .benchmark-done h3 { - color: #6c6c71; + color: var(--text-color-subtle); } .benchmark h3 a, @@ -358,7 +381,7 @@ a.button { } .benchmark-done h3 a:hover { - color: #34AADC; + color: var(--color-primary); text-decoration: underline; } @@ -370,7 +393,7 @@ a.button { } .benchmark-done h4 { - color: #34AADC; + color: var(--color-primary); background-color: none; } @@ -387,8 +410,15 @@ a.button { font-weight: bold; } +#result-summary .benchmark { + text-align: center; + max-width: 100%; + margin: 0; + margin-left: 1.6rem; +} + .benchmark-done .result { - color: #4A4A4A; + color: var(--benchmark-done-result-color); } .benchmark label { @@ -396,10 +426,15 @@ a.button { } .benchmark-done label { - color: #8E8E93; + color: var(--text-color-very-subtle); font-weight: 400; } +.plot svg circle { + fill: var(--color-primary); + opacity: 0.8; +} + @keyframes fadein { from { opacity: 0; diff --git a/JetStreamDriver.js b/JetStreamDriver.js index 76cf9861..7bfa1e2a 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -95,9 +95,16 @@ function displayCategoryScores() { if (!categoryScores) return; + let scoreDetails = `
`; + for (let [category, scores] of categoryScores) { + scoreDetails += ` + ${uiFriendlyScore(geomeanScore(scores))} + + `; + } + scoreDetails += "
"; let summaryElement = document.getElementById("result-summary"); - for (let [category, scores] of categoryScores) - summaryElement.innerHTML += `

${category}: ${uiFriendlyScore(geomeanScore(scores))}

` + summaryElement.innerHTML += scoreDetails; categoryScores = null; } @@ -127,7 +134,6 @@ if (isInBrowser) { const key = keyboardEvent.key; if (key === "d" || key === "D") { showScoreDetails = true; - displayCategoryScores(); } }; @@ -178,7 +184,7 @@ function updateUI() { function uiFriendlyNumber(num) { if (Number.isInteger(num)) return num; - return num.toFixed(3); + return num.toFixed(2); } function uiFriendlyScore(num) { @@ -237,10 +243,8 @@ class Driver { async start() { let statusElement = false; - let summaryElement = false; if (isInBrowser) { statusElement = document.getElementById("status"); - summaryElement = document.getElementById("result-summary"); statusElement.innerHTML = ``; } else if (!dumpJSONResults) console.log("Starting JetStream3"); @@ -308,8 +312,10 @@ class Driver { assert(totalScore > 0, `Invalid total score: ${totalScore}`); if (isInBrowser) { + const summaryElement = document.getElementById("result-summary"); summaryElement.classList.add("done"); - summaryElement.innerHTML = `
${uiFriendlyScore(totalScore)}
`; + summaryElement.innerHTML = `
${uiFriendlyScore(totalScore)}
+ `; summaryElement.onclick = displayCategoryScores; if (showScoreDetails) displayCategoryScores(); @@ -318,7 +324,6 @@ class Driver { console.log("\n"); for (let [category, scores] of categoryScores) console.log(`${category}: ${uiFriendlyScore(geomeanScore(scores))}`); - console.log("\nTotal Score: ", uiFriendlyScore(totalScore), "\n"); } @@ -348,11 +353,13 @@ class Driver { text += `

${benchmark.name}

-

___

`; +

 

+

 

+

`; for (let i = 0; i < scoreIds.length; i++) { const scoreId = scoreIds[i]; const label = description[i]; - text += `___` + text += ` ` } text += `

`; } @@ -692,6 +699,7 @@ class Benchmark { this.isAsync = !!plan.isAsync; this.scripts = null; this.preloads = null; + this.results = []; this._state = BenchmarkState.READY; } @@ -742,8 +750,9 @@ class Benchmark { top.currentResolve(results);`; } - processResults() { - throw new Error("Subclasses need to implement this"); + processResults(results) { + this.results = Array.from(results); + return this.results; } get score() { @@ -1061,6 +1070,36 @@ class Benchmark { for (const [name, value] of scoreEntries) document.getElementById(this.scoreIdentifier(name)).innerHTML = uiFriendlyScore(value); + + this.renderScatterPlot(); + } + + renderScatterPlot() { + const plotContainer = document.getElementById(`plot-${this.name}`); + if (!plotContainer || !this.results || this.results.length === 0) + return; + + const scoreElement = document.getElementById(this.scoreIdentifier("Score")); + const width = scoreElement.offsetWidth; + const height = scoreElement.offsetHeight; + + const padding = 5; + const maxResult = Math.max(...this.results); + const minResult = Math.min(...this.results); + + const xRatio = (width - 2 * padding) / (this.results.length - 1 || 1); + const yRatio = (height - 2 * padding) / (maxResult - minResult || 1); + const radius = Math.max(1.5, Math.min(2.5, 10 - (this.iterations / 10))); + + let circlesSVG = ""; + for (let i = 0; i < this.results.length; i++) { + const result = this.results[i]; + const cx = padding + i * xRatio; + const cy = height - padding - (result - minResult) * yRatio; + const title = `Iteration ${i + 1}: ${uiFriendlyDuration(result)}`; + circlesSVG += `${title}`; + } + plotContainer.innerHTML = `${circlesSVG}`; } updateConsoleAfterRun(scoreEntries) { @@ -1102,13 +1141,7 @@ class DefaultBenchmark extends Benchmark { } processResults(results) { - function copyArray(a) { - const result = []; - for (let x of a) - result.push(x); - return result; - } - results = copyArray(results); + results = super.processResults(results) this.firstIterationTime = results[0]; this.firstIterationScore = toScore(results[0]); @@ -1275,6 +1308,7 @@ class WSLBenchmark extends Benchmark { } processResults(results) { + results = super.processResults(results); this.stdlibTime = results[0]; this.stdlibScore = toScore(results[0]); this.mainRunTime = results[1]; @@ -1332,6 +1366,7 @@ class WasmLegacyBenchmark extends Benchmark { } processResults(results) { + results = super.processResults(results); this.startupTime = results[0]; this.startupScore= toScore(results[0]); this.runTime = results[1];