Last active
August 22, 2023 07:09
-
-
Save trvswgnr/f392b36ca153e738cf72e8f407099322 to your computer and use it in GitHub Desktop.
easy multithreading w/ worker threads nodejs typescript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Worker, isMainThread, parentPort, workerData } from 'worker_threads'; | |
| // Worker thread | |
| if (!isMainThread) { | |
| const workerFunction: (input: any) => any = eval(workerData.workerFunction); | |
| const result = workerFunction(workerData.input); | |
| parentPort?.postMessage(result); | |
| } | |
| // Main thread | |
| class ParIterator<T, R> { | |
| private workers: Worker[] = []; | |
| private tasks: T[] = []; | |
| private results: R[] = []; | |
| private workerFunction: (input: T) => R; | |
| constructor(workerFunction: (input: T) => R, inputs: T[], numWorkers: number) { | |
| this.workerFunction = workerFunction; | |
| this.tasks = inputs; | |
| this.startWorkers(numWorkers); | |
| } | |
| private startWorkers(numWorkers: number): void { | |
| for (let i = 0; i < numWorkers; i++) { | |
| const worker = new Worker(__filename, { | |
| workerData: { workerFunction: this.workerFunction.toString() }, | |
| }); | |
| worker.on('message', (result) => { | |
| this.results.push(result); | |
| if (this.tasks.length > 0) { | |
| worker.postMessage(this.tasks.shift()); | |
| } else { | |
| worker.terminate(); | |
| } | |
| }); | |
| worker.on('error', (error) => { | |
| throw error; | |
| }); | |
| this.workers.push(worker); | |
| } | |
| } | |
| async forEach(callback: (value: R) => void): Promise<void> { | |
| for (const worker of this.workers) { | |
| if (this.tasks.length > 0) { | |
| worker.postMessage(this.tasks.shift()); | |
| } | |
| } | |
| while (this.results.length < this.tasks.length) { | |
| await new Promise((resolve) => setTimeout(resolve, 100)); | |
| } | |
| this.results.forEach(callback); | |
| } | |
| async map(): Promise<R[]> { | |
| for (const worker of this.workers) { | |
| if (this.tasks.length > 0) { | |
| worker.postMessage(this.tasks.shift()); | |
| } | |
| } | |
| while (this.results.length < this.tasks.length) { | |
| await new Promise((resolve) => setTimeout(resolve, 100)); | |
| } | |
| return this.results; | |
| } | |
| } | |
| Array.prototype.parIter = function<T, R>(this: T[], workerFunction: (input: T) => R, numWorkers: number): ParIterator<T, R> { | |
| return new ParIterator(workerFunction, this, numWorkers); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment