| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
i'm so heckin' happy to see this 🎉 🎉 🎉 🎉 regarding the whole name thing, why not use @nodejs/workers? we're pratically being shoved into it due to the owner of workers not wanting to give that name up, and we've been looking for excuses to namespace builtin modules anyway. |
Sorry, something went wrong.
There was a problem hiding this comment.
maybe we should set up some sort of doc macro for this so that we can keep them all in sync if we decide to change the formatting of it.
Sorry, something went wrong.
There was a problem hiding this comment.
Do we know how to do that?
Sorry, something went wrong.
There was a problem hiding this comment.
i would try and gate it in the nativemodule loader instead
Sorry, something went wrong.
There was a problem hiding this comment.
Nit: Remove Used when.
Sorry, something went wrong.
There was a problem hiding this comment.
Nit: Node -> Node.js
Sorry, something went wrong.
There was a problem hiding this comment.
Remove Used when and reword:
The `domain` module cannot be used inside of a worker thread.
Sorry, something went wrong.
There was a problem hiding this comment.
This was one of two outdated error entries anyway. :) It might be cool if our linter could check that entries in this markdown file are also present in lib/internal/errors.h or src/node_errors.h…
Sorry, something went wrong.
There was a problem hiding this comment.
Remove Used when
Sorry, something went wrong.
There was a problem hiding this comment.
A worker has exceeded its memory limit.
Sorry, something went wrong.
There was a problem hiding this comment.
Missing description?
Sorry, something went wrong.
There was a problem hiding this comment.
All attempts to serialize an uncaught exception from a worker failed....or perhaps...
All attempts to serialize an uncaught worker exception failed.
Sorry, something went wrong.
There was a problem hiding this comment.
Remove Used when
Sorry, something went wrong.
There was a problem hiding this comment.
My opinion only but I prefer we leave out *Note*: in nearly all cases.
Sorry, something went wrong.
There was a problem hiding this comment.
I believe *Note*: prefixes were eradicated earlier from the docs.
Sorry, something went wrong.
There was a problem hiding this comment.
My opinion only but I prefer we leave out *Note*: in nearly all cases.
Sorry, something went wrong.
There was a problem hiding this comment.
Nit: Add parentheses, so unfref() and ref(). Also elsewhere in this doc.
Nit: Change comma to period on this line.
Nit: We use `unref`ed rather than `unref'd` in existing documentation so use that here and in line 97, 105, and anywhere else for consistency.
Sorry, something went wrong.
There was a problem hiding this comment.
Add comma before "calling".
Sorry, something went wrong.
There was a problem hiding this comment.
Typo: "This this"
Sorry, something went wrong.
There was a problem hiding this comment.
Typo: non-enumberable -> non-enumerable
Sorry, something went wrong.
There was a problem hiding this comment.
can not -> cannot
Sorry, something went wrong.
There was a problem hiding this comment.
Typo: seperation -> separation
Sorry, something went wrong.
There was a problem hiding this comment.
can not -> cannot
Sorry, something went wrong.
There was a problem hiding this comment.
Typo: expection -> exception
Sorry, something went wrong.
|
<<Native addons are not loadable from worker threads (yet).>> Electron docs: <<Most existing native modules have been written assuming single-threaded environment, using them in Web Workers will lead to crashes and memory corruptions. Note that even if a native Node.js module is thread-safe it's still not safe to load it in a Web Worker because the process.dlopen function is not thread safe.>> I assume you'll have a follow-up PR for process.dlopen? How about require()-ing built-in modules like zlib and fs? mind my lack of knowledge here but are they thread safe? Thank you for this. It's about time Node has built-in threading support... EDIT: Also, how about the File object and JS objects in general? Latest browsers allow us to send JS objects between main thread and worker thread without ceremony, i.e. no longer need to specify as transferrable objects. For File object, I believe the reference to the file on disk is copied, not the entire content of the file. Can we hope for similar functionality in node workers? |
Sorry, something went wrong.
Yes, there will be.
They have been made to be.
The transfer mechanism for general JavaScript objects is implemented identically as browsers do.
There has been interest to implement File and Blob classes as well as the rest of the File API in Node.js, but we no concrete plan has emerged yet. Stay tuned. We will be happy to answer any follow-up question if you file an issue at https://github.com/nodejs/help. Thanks for your interest in worker threads! |
Sorry, something went wrong.
|
Fantastic! really important work you’re doing! Thank you!! |
Sorry, something went wrong.
|
Thank you, really cool stuff! |
Sorry, something went wrong.
|
Hello guys! Am I able to use multi thread with Puppeteer for parallel testing? |
Sorry, something went wrong.
|
@pavel-sindelka puppeteer is not CPU bound typically and runs an off-process Chrome - so that use case would not be a good fit for worker-threads. |
Sorry, something went wrong.
|
@addaleax so is the cluster obsolate? i think cluster is still good right? |
Sorry, something went wrong.
|
with a cluster you can use a load balancer but there is no shared memory out of the box and a process is heavier than a thread... each process can then have multiple threads with shared memory... I think the use case for threads is cpu bound work (vertical scaling) while clusters are for horizontal scaling... would be interested in other opinions |
Sorry, something went wrong.
|
@idibidiart dont you think that the https, mongodb, redis is better using via cluster and for cpu processing is good for threads? look java? so slow with threads via https connections? |
Sorry, something went wrong.
|
I would use threads where shared memory is a plus not a minus and where the work should not be done in the event loop (i.e. any cpu bound work), so yes I'd agree with your statement |
Sorry, something went wrong.
|
thanks for you response. |
Sorry, something went wrong.
|
Guys, do you know how can fix this error? memory leak detected I use like this: require('events').EventEmitter.prototype._maxListeners = 100;
require('events').EventEmitter.defaultMaxListeners = 100;
process.setMaxListeners(100)In both worker and main thread as well. C:\Users\patrikx3\Projects\patrikx3\play\scripts\worker-thread>node-thread main.js Spawning thread 1 Spawning thread 2 Spawning thread 3 Spawning thread 4 Spawning thread 5 Spawning thread 6 Spawning thread 7 Spawning thread 8 Spawning thread 9 Spawning thread 10 Spawning thread 11 Spawning thread 12 Spawning thread 13 Spawning thread 14 Spawning thread 15 Spawning thread 16 Spawning thread 17 Spawning thread 18 Spawning thread 19 Spawning thread 20 (node:9816) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:9816) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 21 error listeners added. Use emitter.setMaxListeners() to increase limit 2018-6-27 08:19:11: Instance 1 2018-6-27 08:19:12: Instance 2 2018-6-27 08:19:13: Instance 3 2018-6-27 08:19:13: Instance 4 2018-6-27 08:19:14: Instance 5 2018-6-27 08:19:15: Instance 6 2018-6-27 08:19:15: Instance 7 2018-6-27 08:19:16: Instance 8 2018-6-27 08:19:17: Instance 9 2018-6-27 08:19:17: Instance 10 2018-6-27 08:19:18: Instance 11 2018-6-27 08:19:19: Instance 12 2018-6-27 08:19:20: Instance 13 2018-6-27 08:19:20: Instance 14 2018-6-27 08:19:21: Instance 15 2018-6-27 08:19:22: Instance 16 2018-6-27 08:19:22: Instance 17 2018-6-27 08:19:23: Instance 18 2018-6-27 08:19:23: Instance 19 2018-6-27 08:19:24: Instance 20 Stopped thread instance 1 This is the from main thread instance 1: 102334155 Stopped thread instance 1 Stopped thread instance 2 This is the from main thread instance 2: 102334155 Stopped thread instance 2 Stopped thread instance 3 This is the from main thread instance 3: 102334155 Stopped thread instance 3 Stopped thread instance 4 This is the from main thread instance 4: 102334155 Stopped thread instance 4 Stopped thread instance 5 This is the from main thread instance 5: 102334155 Stopped thread instance 5 2018-6-27 08:19:28: Instance 6 2018-6-27 08:19:28: Instance 7 2018-6-27 08:19:28: Instance 8 2018-6-27 08:19:28: Instance 9 2018-6-27 08:19:28: Instance 10 2018-6-27 08:19:28: Instance 11 2018-6-27 08:19:28: Instance 12 2018-6-27 08:19:28: Instance 13 2018-6-27 08:19:28: Instance 14 2018-6-27 08:19:28: Instance 15 2018-6-27 08:19:28: Instance 16 2018-6-27 08:19:28: Instance 17 2018-6-27 08:19:28: Instance 18 2018-6-27 08:19:28: Instance 19 2018-6-27 08:19:28: Instance 20 Stopped thread instance 6 This is the from main thread instance 6: 102334155 Stopped thread instance 6 Stopped thread instance 7 This is the from main thread instance 7: 102334155 Stopped thread instance 7 Stopped thread instance 8 This is the from main thread instance 8: 102334155 Stopped thread instance 8 Stopped thread instance 9 This is the from main thread instance 9: 102334155 Stopped thread instance 9 Stopped thread instance 10 This is the from main thread instance 10: 102334155 Stopped thread instance 10 Stopped thread instance 11 This is the from main thread instance 11: 102334155 Stopped thread instance 11 Stopped thread instance 12 This is the from main thread instance 12: 102334155 Stopped thread instance 12 Stopped thread instance 13 This is the from main thread instance 13: 102334155 Stopped thread instance 13 Stopped thread instance 14 This is the from main thread instance 14: 102334155 Stopped thread instance 14 Stopped thread instance 15 This is the from main thread instance 15: 102334155 Stopped thread instance 15 Stopped thread instance 16 This is the from main thread instance 16: 102334155 Stopped thread instance 16 Stopped thread instance 17 This is the from main thread instance 17: 102334155 Stopped thread instance 17 Stopped thread instance 18 This is the from main thread instance 18: 102334155 Stopped thread instance 18 Stopped thread instance 19 This is the from main thread instance 19: 102334155 Stopped thread instance 19 Stopped thread instance 20 This is the from main thread instance 20: 102334155 Stopped thread instance 20 #The code main.jsrequire('events').EventEmitter.prototype._maxListeners = 100;
require('events').EventEmitter.defaultMaxListeners = 100;
process.setMaxListeners(100)
const {
Worker, isMainThread, parentPort, workerData
} = require('worker_threads');
intervalCounter = {}
let instance = 0
const clearMainThread = (thisInstance) => {
clearInterval(intervalCounter[thisInstance])
console.log(`Stopped thread instance ${thisInstance}`)
}
const threads = () => {
return new Promise((resolve, reject) => {
const thisInstance = ++instance
intervalCounter[thisInstance] = setInterval(() => {
console.log(`${new Date().toLocaleString()}: Instance ${thisInstance}`)
}, 1000)
const worker = new Worker(`${__dirname}/thread.js`, {
workerData: {
instance: thisInstance
},
});
worker.on('message', (data) => {
clearMainThread(thisInstance)
console.log(data)
resolve(data)
});
worker.on('error', (err) => {
clearMainThread(thisInstance)
console.log(err)
reject(err)
});
worker.on('exit', (code) => {
clearMainThread(thisInstance)
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
})
})
}
const threadCounts = 20
for (let threadCount = 0; threadCount < threadCounts; threadCount++) {
console.log(`Spawning thread ${instance + 1}`)
threads()
}thread.jsrequire('events').EventEmitter.prototype._maxListeners = 100;
require('events').EventEmitter.defaultMaxListeners = 100;
process.setMaxListeners(100)
const {
Worker, isMainThread, parentPort, workerData
} = require('worker_threads');
function fib(n) {
// console.log(`Count instance ${workerData.instance}: fib(${n}) `)
if (n > 1) {
return fib(n - 1) + fib(n - 2)
} else {
return n;
}
}
const fibResult = fib(40)
//console.log(`This is the from thread: ${fibResult}`)
parentPort.postMessage(`This is the from main thread instance ${workerData.instance}: ${fibResult}`);What is weird is if i set setInterval for pinging from 1000 to 2000 ms it shows now leakC:\Users\patrikx3\Projects\patrikx3\play\scripts\worker-thread>node-thread main.js Spawning thread 1 Spawning thread 2 Spawning thread 3 Spawning thread 4 Spawning thread 5 Spawning thread 6 Spawning thread 7 Spawning thread 8 Spawning thread 9 Spawning thread 10 Spawning thread 11 Spawning thread 12 Spawning thread 13 Spawning thread 14 Spawning thread 15 Spawning thread 16 Spawning thread 17 Spawning thread 18 Spawning thread 19 Spawning thread 20 2018-6-27 08:26:26: Instance 1 2018-6-27 08:26:28: Instance 2 2018-6-27 08:26:29: Instance 3 2018-6-27 08:26:30: Instance 4 2018-6-27 08:26:31: Instance 5 2018-6-27 08:26:32: Instance 6 2018-6-27 08:26:33: Instance 7 2018-6-27 08:26:34: Instance 8 2018-6-27 08:26:35: Instance 9 2018-6-27 08:26:36: Instance 10 2018-6-27 08:26:36: Instance 11 2018-6-27 08:26:37: Instance 12 2018-6-27 08:26:37: Instance 13 2018-6-27 08:26:38: Instance 14 2018-6-27 08:26:38: Instance 15 2018-6-27 08:26:39: Instance 16 2018-6-27 08:26:39: Instance 17 2018-6-27 08:26:39: Instance 18 2018-6-27 08:26:40: Instance 19 2018-6-27 08:26:40: Instance 20 2018-6-27 08:26:40: Instance 1 2018-6-27 08:26:40: Instance 2 2018-6-27 08:26:40: Instance 3 2018-6-27 08:26:40: Instance 4 2018-6-27 08:26:40: Instance 5 2018-6-27 08:26:40: Instance 6 2018-6-27 08:26:40: Instance 7 2018-6-27 08:26:40: Instance 8 2018-6-27 08:26:40: Instance 9 2018-6-27 08:26:40: Instance 10 2018-6-27 08:26:40: Instance 11 2018-6-27 08:26:40: Instance 12 2018-6-27 08:26:40: Instance 13 This is the from main thread instance 1: 102334155 This is the from main thread instance 2: 102334155 This is the from main thread instance 3: 102334155 This is the from main thread instance 5: 102334155 This is the from main thread instance 4: 102334155 This is the from main thread instance 6: 102334155 This is the from main thread instance 7: 102334155 This is the from main thread instance 8: 102334155 This is the from main thread instance 9: 102334155 This is the from main thread instance 10: 102334155 This is the from main thread instance 11: 102334155 This is the from main thread instance 12: 102334155 This is the from main thread instance 13: 102334155 This is the from main thread instance 14: 102334155 This is the from main thread instance 15: 102334155 This is the from main thread instance 16: 102334155 This is the from main thread instance 17: 102334155 This is the from main thread instance 18: 102334155 This is the from main thread instance 19: 102334155 This is the from main thread instance 20: 102334155 |
Sorry, something went wrong.
|
i test a lot but about 50 threads it freezes the windows. I think the Java and C# people wil understand threads are kaka... |
Sorry, something went wrong.
|
i have tested many benchmarks, but the threads for computing are faster 🥇 . not faster for many threads but the memory usage is smaller, so threads are totally vialable. 💯 |
Sorry, something went wrong.
|
As the author noted, this is work in progress and still in experimental stage ... you can certainly have more threads than much heavier nodejs processes/instances on any given machine... threads give you shared memory with its pros and cons... without threads, nodejs is designed for I/O bound work like fetching something from db... with threads it can do cpu bound work (potentially in parallel if you design it that way) outside the main thread so node can remain responsive to I/O, while processing in background... but even threads are limited by the number of cores and memory available ... |
Sorry, something went wrong.
|
@addaleax This landed without proper error documentation. |
Sorry, something went wrong.
Sorry, something went wrong.
|
When can i expect LTS of thread? Eagerly waiting... |
Sorry, something went wrong.
|
Workers are likely to be experimental for a while. They'll be in 10.x after it goes LTS but still as experimental. |
Sorry, something went wrong.
|
Thanks 👍 |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Hi everyone! 👋
This PR adds threading support for to Node.js. I realize that this is not exactly a small PR and is going to take a while to review, so: I appreciate comments, questions (any kind, as long as it’s somewhat related 😺), partial reviews and all other feedback from anybody, not just Node.js core collaborators.
The super-high-level description of the implementation here is that Workers can share and transfer memory, but not JS objects (they have to be cloned for transferring), and not yet handles like network sockets.
FAQ
See https://gist.github.com/benjamingr/3d5e86e2fb8ae4abe2ab98ffe4758665
Example usage
Feature set
The communication between threads largely builds on the MessageChannel Web API. Transferring ArrayBuffers and sharing memory through SharedArrayBuffers is supported.
Almost the entire Node.js core API is require()able or importable.
Some notable differences:
(Keep in mind that PRs can change significantly based on reviews.)
Comparison with child_process and cluster
Workers are conceptually very similar to child_process and cluster.
Some of the key differences are:
Benchmarks
$ ./node benchmark/cluster/echo.js cluster/echo.js n=100000 sendsPerBroadcast=1 payload="string" workers=1: 33,647.30473442063 cluster/echo.js n=100000 sendsPerBroadcast=10 payload="string" workers=1: 12,927.907405288383 cluster/echo.js n=100000 sendsPerBroadcast=1 payload="object" workers=1: 28,496.37373941151 cluster/echo.js n=100000 sendsPerBroadcast=10 payload="object" workers=1: 8,975.53747186485 $ ./node --experimental-worker benchmark/worker/echo.js worker/echo.js n=100000 sendsPerBroadcast=1 payload="string" workers=1: 88,044.32902365089 worker/echo.js n=100000 sendsPerBroadcast=10 payload="string" workers=1: 39,873.33697018837 worker/echo.js n=100000 sendsPerBroadcast=1 payload="object" workers=1: 64,451.29132425621 worker/echo.js n=100000 sendsPerBroadcast=10 payload="object" workers=1: 22,325.635443739284A caveat here is that startup performance for Workers using this model is still relatively slow (I don’t have exact numbers, but there’s definitely overhead).
Regarding semverness:
The only breaking change here is the introduction of a new top-level module. The name is currently worker, this is not under a scope as suggested in nodejs/TSC#389. It seems like the most natural name for this by far.
I’ve reached out to the owner of the worker module on npm, who declined to provide the name for this purpose – the package has 57 downloads/week, so whether we consider this semver-major because of that is probably a judgement call.
Alternatively, I’d suggest using workers – it’s not quite what we’re used to in core (e.g. child_process), but the corresponding npm package is essentially just a placeholder.
Acknowledgements
People I’d like to thank for their code, comments and reviews for this work in its original form, in no particular order:
… and finally @petkaantonov for a lot of inspiration and the ability to compare with previous work on this topic.
Individual commits
src: cleanup per-isolate state on platform on isolate unregister
Clean up once all references to an Isolate* are gone from the
NodePlatform, rather than waiting for the PerIsolatePlatformData
struct to be deleted since there may be cyclic references between
that struct and the individual tasks.
src: fix MallocedBuffer move assignment operator
src: break out of timers loop if !can_call_into_js()
Otherwise, this turns into an infinite loop.
src: simplify handle closing
Remove one extra closing state and use a smart pointer for
deleting HandleWraps.
worker: implement MessagePort and MessageChannel
Implement MessagePort and MessageChannel along the lines of
the DOM classes of the same names. MessagePorts initially
support transferring only ArrayBuffers.
worker: support MessagePort passing in messages
Support passing MessagePort instances through other MessagePorts,
as expected by the MessagePort spec.
worker: add SharedArrayBuffer sharing
Logic is added to the MessagePort mechanism that
attaches hidden objects to those instances when they are transferred
that track their lifetime and maintain a reference count, to make
sure that memory is freed at the appropriate times.
src: add Env::profiler_idle_notifier_started()
src: move DeleteFnPtr into util.h
This is more generally useful than just in a crypto context.
worker: initial implementation
Implement multi-threading support for most of the API.
test: add test against unsupported worker features
worker: restrict supported extensions
Only allow .js and .mjs extensions to provide future-proofing
for file type detection.
src: enable stdio for workers
Provide stdin, stdout and stderr options for the Worker
constructor, and make these available to the worker thread
under their usual names.
The default for stdin is an empty stream, the default for
stdout and stderr is redirecting to the parent thread’s
corresponding stdio streams.
benchmark: port cluster/echo to worker
worker: improve error (de)serialization
Rather than passing errors using some sort of string representation,
do a best effort for faithful serialization/deserialization of
uncaught exception objects.
test,tools: enable running tests under workers
Enable running tests inside workers by passing --worker
to tools/test.py. A number of tests are marked as skipped,
or have been slightly altered to fit the different environment.
Other work
I know that teams from Microsoft (/cc @fs-eire @helloshuangzi) and Alibaba (/cc @aaronleeatali) have been working on forms of multithreading that have higher degrees of interaction between threads, such as sharing code and JS objects. I’d love if you could take a look at this PR and see how well it aligns with your own work, and what conflicts there might be. (From what I’ve seen of the other code, I’m actually quite optimistic that this PR is just going to help everybody.)
Checklist