diff --git a/JetStream.css b/JetStream.css index c04d205f..3e50c2e7 100644 --- a/JetStream.css +++ b/JetStream.css @@ -304,6 +304,9 @@ a.button { .benchmark h3 { color: rgb(183, 183, 183); } +.benchmark.grouped .benchmark-name { + font-style: italic; +} .benchmark-running h4, .benchmark-running .result, .benchmark-running label { color: #86D9FF; diff --git a/JetStreamDriver.js b/JetStreamDriver.js index 76cf9861..ee3fb5ec 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -221,9 +221,8 @@ class Driver { this.isReady = false; this.isDone = false; this.errors = []; - // Make benchmark list unique and sort it. - this.benchmarks = Array.from(new Set(benchmarks)); - this.benchmarks.sort((a, b) => a.plan.name.toLowerCase() < b.plan.name.toLowerCase() ? 1 : -1); + this.benchmarks = this.setupBenchmarks(benchmarks) + this.scoreGroups = this.setupScoreGroups(); assert(this.benchmarks.length, "No benchmarks selected"); // TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs. // the global `fileLoader` cache. @@ -235,6 +234,28 @@ class Driver { this.counter.failedPreloadResources = 0; } + setupBenchmarks(benchmarks) { + // Make benchmark list unique and sort it. + benchmarks = Array.from(new Set(benchmarks)); + benchmarks.sort((a, b) => a.plan.name.toLowerCase() < b.plan.name.toLowerCase() ? 1 : -1); + return benchmarks; + } + + setupScoreGroups() { + const groups = new Map(); + for (const benchmark of benchmarks) { + const scoreGroupName = benchmark.plan.scoreGroup ?? benchmark.name; + let scoreGroup = groups.get(scoreGroupName); + if (!scoreGroup) { + scoreGroup = []; + groups.set(scoreGroupName, scoreGroup); + } + scoreGroup.push(benchmark); + } + return Array.from(groups.entries()).map( + ([groupName, benchmarks]) => new ScoreGroup(groupName, benchmarks)); + } + async start() { let statusElement = false; let summaryElement = false; @@ -284,22 +305,22 @@ class Driver { } const allScores = []; - for (const benchmark of this.benchmarks) { - const score = benchmark.score; - assert(score > 0, `Invalid ${benchmark.name} score: ${score}`); + for (const scoreGroup of this.scoreGroups) { + const score = scoreGroup.score; + assert(score > 0, `Invalid ${scoreGroup.name} score: ${score}`); allScores.push(score); } categoryScores = new Map; - for (const benchmark of this.benchmarks) { - for (let category of Object.keys(benchmark.subScores())) + for (const scoreGroup of this.scoreGroups) { + for (let category of Object.keys(scoreGroup.subScores())) categoryScores.set(category, []); } - for (const benchmark of this.benchmarks) { - for (let [category, value] of Object.entries(benchmark.subScores())) { + for (const scoreGroup of this.scoreGroups) { + for (let [category, value] of Object.entries(scoreGroup.subScores())) { const arr = categoryScores.get(category); - assert(value > 0, `Invalid ${benchmark.name} ${category} score: ${value}`); + assert(value > 0, `Invalid ${scoreGroup.name} ${category} score: ${value}`); arr.push(value); } } @@ -343,11 +364,14 @@ class Driver { const scoreIds = benchmark.scoreIdentifiers(); const overallScoreId = scoreIds.pop(); + let classes = "benchmark" + let isGroupedBenchmark =benchmark.scoreGroup.size > 1 + if (isGroupedBenchmark) + classes += " grouped"; if (isInBrowser) { - text += - `
`; for (let i = 0; i < scoreIds.length; i++) { const scoreId = scoreIds[i]; @@ -603,6 +627,37 @@ class Scripts { } } +class ScoreGroup { + constructor(name, benchmarks) { + this.name = name; + this.benchmarks = benchmarks; + benchmarks.forEach(benchmark => benchmark.scoreGroup = this); + } + + get size() { + return this.benchmarks.length; + } + + add(benchmark) { + assert(!this.benchmarks.has(benchmark)); + this.benchmarks.add(benchmark); + } + + get score() { + return geomeanScore(this.benchmarks.map(each => each.score)); + } + + subScores() { + const allSubScores = this.benchmarks.map(each => each.subScores()); + const subScores = { __proto__: null}; + for (const name of Object.keys(allSubScores[0])) { + subScores[name] = geomeanScore(allSubScores.map(each => each[name])); + } + return subScores; + } +} + + class ShellScripts extends Scripts { run() { let globalObject; @@ -693,6 +748,7 @@ class Benchmark { this.scripts = null; this.preloads = null; this._state = BenchmarkState.READY; + this.scoreGroup = undefined; } processTags(rawTags) { @@ -2387,6 +2443,7 @@ const SUNSPIDER_TESTS = [ "string-unpack-code", "tagcloud", ]; + for (const test of SUNSPIDER_TESTS) { BENCHMARKS.push(new DefaultBenchmark({ name: `${test}-SP`, @@ -2394,9 +2451,11 @@ for (const test of SUNSPIDER_TESTS) { `./SunSpider/${test}.js` ], tags: ["Default", "SunSpider"], + scoreGroup: "SunSpider", })); } + // WTB (Web Tooling Benchmark) tests const WTB_TESTS = [ "acorn",