// Benchmark measures time it takes to send a message to a group of workers one // at a time and wait for a response from all of them. Just a general // throughput and consistency benchmark. const data = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n"; const workerCount = 4; const cmdsPerWorker = 400; export interface ResolvableMethods { resolve: (value?: T | PromiseLike) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any reject: (reason?: any) => void; } export type Resolvable = Promise & ResolvableMethods; export function createResolvable(): Resolvable { let methods: ResolvableMethods; const promise = new Promise( (resolve, reject): void => { methods = { resolve, reject }; } ); // TypeScript doesn't know that the Promise callback occurs synchronously // therefore use of not null assertion (`!`) return Object.assign(promise, methods!) as Resolvable; } function handleAsyncMsgFromWorker( promiseTable: Map>, msg: { cmdId: number; data: string } ): void { const promise = promiseTable.get(msg.cmdId); if (promise === null) { throw new Error(`Failed to find promise: cmdId: ${msg.cmdId}, msg: ${msg}`); } promise.resolve(data); } async function main(): Promise { const workers: Array<[Map>, Worker]> = []; for (let i = 1; i <= workerCount; ++i) { const worker = new Worker("./subdir/bench_worker.ts"); const promise = new Promise( (resolve): void => { worker.onmessage = (e): void => { if (e.data.cmdId === 0) resolve(); }; } ); worker.postMessage({ cmdId: 0, action: 2 }); await promise; workers.push([new Map(), worker]); } // assign callback function for (const [promiseTable, worker] of workers) { worker.onmessage = (e): void => { handleAsyncMsgFromWorker(promiseTable, e.data); }; } for (const cmdId of Array(cmdsPerWorker).keys()) { const promises: Array> = []; for (const [promiseTable, worker] of workers) { const promise = createResolvable(); promiseTable.set(cmdId, promise); worker.postMessage({ cmdId: cmdId, action: 1, data }); promises.push(promise); } for (const promise of promises) { await promise; } } for (const [, worker] of workers) { worker.postMessage({ action: 3 }); await worker.closed; // Required to avoid a cmdId not in table error. } console.log("Finished!"); } main();