What's the best way to make a time intensive function, such as image manipulation, run asynchronously to allow other code to run or to allow multiple instances of said function run in parallel? (can be Node specific) For example like fs.readFile() or fetch() (XHR).
-
3**[Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)** are what you want. – Scott Marcus Jun 12 '18 at 19:18
-
Thanks, will look into it. – Drejk Jun 12 '18 at 19:21
-
1If you want Node-specific, write it in C++ as an addon module, and expose it with a signature that accepts a callback or returns a promise, and use the libuv patterns in v8 to perform it as a threaded task. That'll make it asynchronous without losing any efficiency due to yielding to the event loop intermittently. Alternatively, you could leave it synchronous and run it as a `child_process` to put it in a separate thread. – Patrick Roberts Jun 12 '18 at 19:46
-
2Thanks. So essentially Web Workers is the browser solution and child_process / cluster the Node solution, right? As for addon modules, I don't really know c++ or any other native language, just js and python, so I would prefer using what I know (somewhat), at least for now. – Drejk Jun 12 '18 at 20:06
-
@Drejk that is correct – Patrick Roberts Jun 12 '18 at 20:09
1 Answers
Because node.js runs your Javascript as single threaded (only one piece of Javascript ever executing at a time), if your compute intensive image manipulation is currently all Javascript code, then your options for running your image manipulation in parallel with other Javascript are as follows:
Fire up one or more worker processes (which can run node.js code or any other program you want) and do the image manipulation there in a separate process. They can then communicate back the result with any form of interprocess communication. This is probably the most common way to solve CPU intensive issues in node.js (offloading the CPU intensive stuff to other processes). You can use the child_process module to start these other processes and to communicate with them.
Write a native code add-on for node.js that uses native threads and native code to do the image manipulation and that offers an asynchronous interface to node.js code. You can then call that interface asynchronously from node.js and be notified when it is complete, but node.js will be free to work on other things while it is working.
Break the image manipulation into very small work chunks such that you can execute a small chunk of work (like a few ms of work), schedule the next chunk of work to run in a few ms and return control back to the event sub-system so it can process other events interleaved with your small chunks of work. FYI, design complicated code to run in small chunks is hard. You end up having to essentially build a state machine that can do a small amount of work and return, only to be called later to do some more work.

- 683,504
- 96
- 985
- 979
-
Agreed with your commentary about approach #3. In addition, it severely limits performance with the inevitable de-optimizations in order to introduce a state-machine for the asynchronicity, and repeatedly yielding to other events in between. #2 would be the "ideal" approach for long term, and #1 seems to be a good balance between ease of implementation and performance. – Patrick Roberts Jun 12 '18 at 20:13
-
@PatrickRoberts - No. That comment got put on the wrong question. Sorry, I will delete it here. – jfriend00 Jun 13 '18 at 00:21