Skip to content
Graham Wakefield edited this page Jun 1, 2021 · 3 revisions

Why threads?

  • Move heavy or slow or unpredictable processing to a parallel thread, so that it doesn't interrupt important things (e.g. VR rendering) in the main thread.
  • Less expensive and less complex to share memory than when using fork() to a new process

Node.js workers

const { Worker } = require('worker_threads')

const worker = new Worker('./myworker.js', { workerData: "any simple JS data here" });
worker.on('message', msg => console.log(msg));
worker.on('error', err => console.error(err));
worker.on('exit', code => {
	if (code !== 0) console.error(`Worker stopped with exit code ${code}`)
	else console.log("worker done")
});
worker.postMessage("hi")

And myworker.js:

const { workerData, parentPort } = require('worker_threads')

console.log("hello from worker", workerData)
parentPort.postMessage({ msg: "hello "+workerData })
parentPort.on("message", msg => console.log(msg))

Alternatively, rather than running a file you can run code directly using new Worker(code, { eval: true, workerData:... })

Sharing data between threads

Normally, the workerData is copied when a thread starts. It can contain any JSON valid data, and also even recursive structures and binary arrays, but they will be copied.

If you want to share binary data (only binary data) you can use SharedArrayBuffer:

let sab = new SharedArrayBuffer(bytesize)
let floats = new Float32Array(sab); // etc.
const worker = new Worker(script, {workerData: floats})

Now this array of floats can be read & written from both threads.

Frustratingly, support for SharedArrayBuffer doesn't seem to be part of the C N-API just yet. That means we can't share binary data directly between both C++ addon modules and multiple workers. A workaround perhaps would be using a common external_arraybuffer defined in a C++ module and used by both workers.

See also Atomics.wait/Atomics.notify

Clone this wiki locally