2019-08-06 11:15:12 +02:00

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
}
}