@jonahsnider/benchmark
Version:
A Node.js benchmarking library with support for multithreading and TurboFan optimization isolation.
69 lines • 3.81 kB
JavaScript
var _Thread_instances, _Thread_worker, _Thread_workerOptions, _Thread_createWorker, _Thread_onExit, _Thread_onAbort;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
import assert from 'node:assert/strict';
import { once } from 'node:events';
import { Worker } from 'node:worker_threads';
import { Suite } from './suite.js';
import { ThreadWorker } from './types/index.js';
import { compatibleImport } from './utils.js';
const WORKER_PATH = new URL('thread-worker.js', import.meta.url);
/**
* Runs a {@link (Suite:class)} in a separate thread.
*/
export class Thread {
static async init(suiteFilepath) {
const suite = await compatibleImport(suiteFilepath);
assert.ok(suite instanceof Suite, new TypeError(`Expected "${suiteFilepath}" to export a Suite instance`));
return new Thread(suite, suiteFilepath);
}
constructor(suite, suitePath) {
_Thread_instances.add(this);
_Thread_worker.set(this, void 0);
_Thread_workerOptions.set(this, void 0);
this.name = suite.name;
this.filepath = suitePath;
const workerData = {
suitePath,
};
__classPrivateFieldSet(this, _Thread_workerOptions, {
workerData,
}, "f");
__classPrivateFieldSet(this, _Thread_worker, __classPrivateFieldGet(this, _Thread_instances, "m", _Thread_createWorker).call(this), "f");
__classPrivateFieldGet(this, _Thread_worker, "f").on('exit', __classPrivateFieldGet(this, _Thread_instances, "m", _Thread_onExit).bind(this));
__classPrivateFieldGet(this, _Thread_worker, "f").unref();
}
async run(abortSignal) {
const runMessage = { kind: ThreadWorker.Message.Kind.Run };
// Worker must be run before an abort signal is sent
__classPrivateFieldGet(this, _Thread_worker, "f").postMessage(runMessage);
const onAbortListener = __classPrivateFieldGet(this, _Thread_instances, "m", _Thread_onAbort).bind(this);
abortSignal?.addEventListener('abort', onAbortListener, { once: true });
const message = once(__classPrivateFieldGet(this, _Thread_worker, "f"), 'message').finally(() => abortSignal?.removeEventListener('abort', onAbortListener));
const [response] = (await message);
switch (response.kind) {
case ThreadWorker.Response.Kind.Results: {
return response.results;
}
case ThreadWorker.Response.Kind.Error: {
// Note: Structured clone algorithm has weird behavior with Error instances - see https://github.com/nodejs/help/issues/1558#issuecomment-431142715 and https://github.com/nodejs/node/issues/26692#issuecomment-658010376
throw response.error;
}
default: {
throw new RangeError(`Unknown response kind`);
}
}
}
}
_Thread_worker = new WeakMap(), _Thread_workerOptions = new WeakMap(), _Thread_instances = new WeakSet(), _Thread_createWorker = function _Thread_createWorker() {
return new Worker(WORKER_PATH, __classPrivateFieldGet(this, _Thread_workerOptions, "f"));
}, _Thread_onExit = async function _Thread_onExit(code) {
// This prevents the main thread from hanging when the worker is not `unref`'d
await __classPrivateFieldGet(this, _Thread_worker, "f").terminate();
// Create a new worker
__classPrivateFieldSet(this, _Thread_worker, __classPrivateFieldGet(this, _Thread_instances, "m", _Thread_createWorker).call(this), "f");
throw new Error(`Worker exited with code ${code}`);
}, _Thread_onAbort = function _Thread_onAbort() {
const abortMessage = { kind: ThreadWorker.Message.Kind.Abort };
__classPrivateFieldGet(this, _Thread_worker, "f").postMessage(abortMessage);
};
//# sourceMappingURL=thread.js.map