iso-bench
Version:
Small benchmark library focused in avoiding optimization/deoptimization pollution between tests by isolating them.
111 lines (110 loc) • 3.84 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ForkContext = void 0;
const Fork_1 = require("./Fork");
class ForkContext {
_test;
_processors;
_resolve;
_benchName;
_ended = false;
constructor(_test, _processors, _resolve, _benchName) {
this._test = _test;
this._processors = _processors;
this._resolve = _resolve;
this._benchName = _benchName;
}
start() {
const setup = {
testIndex: this._test.index,
benchName: this._benchName
};
const worker = Fork_1.Fork.fork({
["ISO_BENCH_SETUP"]: JSON.stringify(setup)
});
this._listenForCompletionMessage(worker.stdio[3]);
this._listenForProcessExit(worker);
}
_processMessage(msg) {
if (!this._ended) {
if (msg.error != null) {
this._test.opMs = 0;
this._test.error = msg.error;
this._ended = true;
this._resolve();
}
else if (msg.done) {
this._ended = true;
const totalSamples = this._test.options.samplesPerSpawn * this._test.options.spawns;
if (this._test.samples.length >= totalSamples) {
this._resolve();
}
else {
const forkContext = new ForkContext(this._test, this._processors, this._resolve, this._benchName);
forkContext.start();
}
}
else {
const sample = {
cycles: msg.cycles,
time: msg.diff,
ops: msg.cycles / msg.diff
};
this._test.samples.push(sample);
this._test.totalTime += msg.diff;
this._test.opMs = this._test.samples.reduce((total, sample) => total + sample.ops, 0) / this._test.samples.length;
for (const processor of this._processors) {
processor.sample && processor.sample(this._test, sample);
}
}
}
}
_listenForCompletionMessage(stream) {
let size = null;
stream.on("readable", () => {
try {
while (stream.readable) {
if (this._ended) {
break;
}
else if (size == null) {
const buffer = stream.read(2);
if (buffer && buffer.length === 2) {
size = buffer.readUint16LE();
}
else {
break;
}
}
else {
const buffer = stream.read(size);
if (buffer && buffer.length === size) {
size = null;
const message = JSON.parse(String(buffer));
this._processMessage(message);
}
}
}
}
catch (e) {
this._processMessage({
error: String(e)
});
}
});
}
_listenForProcessExit(worker) {
const errBuffer = [];
worker.stderr.on("data", data => errBuffer.push(data));
worker.on("close", (code) => {
let err = `Process ended prematurely. Exit code: ${code}`;
if (errBuffer.length > 0) {
err = `${err}. Error: ${Buffer.concat(errBuffer).toString()}`;
}
this._processMessage({
error: err
});
});
}
}
exports.ForkContext = ForkContext;