112 lines
2.1 KiB
JavaScript
112 lines
2.1 KiB
JavaScript
export class BenchmarkSuite {
|
|
constructor() {
|
|
this.state = 'initialized'
|
|
this.cases = new CasesIterator([])
|
|
this.reset()
|
|
this.onChange = () => {}
|
|
}
|
|
|
|
reset() {
|
|
this.cases.reset()
|
|
this.stats = this.cases.getInitialStats()
|
|
}
|
|
|
|
setBenchmarkType(benchmarktype) {
|
|
this.benchmarktype = benchmarktype
|
|
this.onChange()
|
|
}
|
|
|
|
setCases(cases) {
|
|
this.cases = new CasesIterator(cases)
|
|
this.stats = this.cases.getInitialStats()
|
|
this.onChange()
|
|
}
|
|
|
|
addStat(name, val) {
|
|
this.stats[name] = [...this.stats[name], val]
|
|
}
|
|
|
|
async measureNext() {
|
|
let currentCase = this.cases.next()
|
|
this.benchmarktype.setCase(currentCase)
|
|
this.addStat(currentCase.name, await this.benchmarktype.run())
|
|
}
|
|
|
|
async run() {
|
|
while (this.state === 'running' && this.cases.hasNext()) {
|
|
await this.measureNext()
|
|
this.onChange()
|
|
await freeEventLoop()
|
|
}
|
|
|
|
switch (this.state) {
|
|
case 'running':
|
|
this.state = 'finished'
|
|
break
|
|
case 'stop_requested':
|
|
this.reset()
|
|
this.state = 'initialized'
|
|
break
|
|
case 'pause_requested':
|
|
this.state = this.cases.hasNext() ? 'paused' : 'finished'
|
|
break
|
|
}
|
|
this.onChange()
|
|
}
|
|
|
|
start() {
|
|
this.state = 'running'
|
|
this.run()
|
|
}
|
|
|
|
pause() {
|
|
this.state = 'pause_requested'
|
|
}
|
|
|
|
stop() {
|
|
this.state = 'stop_requested'
|
|
this.run()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Promise that uses setTimeout to resolve.
|
|
* This is a hack to free the eventloop from microtasks.
|
|
* Without this rendering blocks during benchmarks.
|
|
*/
|
|
async function freeEventLoop() {
|
|
return new Promise(resolve => setTimeout(resolve, 0))
|
|
}
|
|
|
|
class CasesIterator {
|
|
constructor(cases) {
|
|
this.cases = cases
|
|
this.idx = -1
|
|
}
|
|
|
|
current() {
|
|
return this.cases[this.idx]
|
|
}
|
|
|
|
hasNext() {
|
|
return this.idx + 1 < this.cases.length
|
|
}
|
|
|
|
next() {
|
|
this.idx = this.idx + 1
|
|
return this.idx < this.cases.length ? this.current() : null
|
|
}
|
|
|
|
reset() {
|
|
this.idx = -1
|
|
}
|
|
|
|
getInitialStats() {
|
|
let stats = {}
|
|
for (let c of this.cases) {
|
|
stats[c.name] = []
|
|
}
|
|
return stats
|
|
}
|
|
}
|