Node.js specializes in data-intensive real-time (data-intensive real-time) interactive scenarios. Data-intensive real-time applications, however, are not just I/o-intensive tasks, but when encountering CPU-intensive tasks, For example, to decrypt data (node.bcrypt.js), data compression and decompression (Node-tar), or according to the user's identity of the image to do some personalized processing, in these scenarios, the main thread is committed to do a complex CPU calculation, I/O request queue tasks are blocked.
The event loop of the Node.js main thread executes all Tasks/events along the order of the event queue, so that other callbacks, listeners, timeouts, Nexttick () functions do not get the chance to run until either of these tasks/events itself is completed. Because the Blocked event loop has no chance to process them at all, the best thing in the program is to slow down, and the worst is to stop and die.
A viable solution is the new process, through IPC communication, the CPU-intensive task to the child process, after the child process is computed, and then through the IPC message to inform the main process, and return the results to the main process.
Compared with creating threads, the system resource occupancy rate of new process is large, and the communication efficiency between processes is not high. If you can not open a new process but a new thread, the CPU time-consuming task to a worker to do, and then the main thread immediately return, processing other I/O requests, wait until the worker thread is calculated, notify the main thread and return the result to the main thread. Then, in a scenario where I/o-intensive and CPU-intensive services are also encountered, node's main thread becomes relaxed and can remain highly responsive.
As a result, a more excellent solution than the open process is:
Instead of opening the process, the CPU time-consuming operation is handed over to a worker thread in the process.
CPU time-consuming operation of the specific logic support through C + + and JS implementation.
JS uses this mechanism similar to the use of I/O library, convenient and efficient.
Running a standalone V8 VM in a new thread executes concurrently with the main thread's VM, and this thread must be hosted by us.
To achieve the above four goals, we added a backgroundthread thread to the node, which will be explained in detail later in this article. In concrete implementation, add a Pt_c built-in C + + module for node. This module is responsible for encapsulating CPU time-consuming operations into a task, throwing it to the backgroundthread and then returning immediately. The specific logic is processed in another thread, and after completion, the result is set and the main thread is notified. This process is very similar to asynchronous I/O requests. The specific logic is as follows:
node provides a mechanism to give CPU-time-consuming operations to other threads to do so, and then set the results to notify the main thread to perform the callback function when the execution is complete. Here's a piece of code to illustrate this process:
int main () {
loop = Uv_default_loop ();
int Data[fib_until];
uv_work_t Req[fib_until];
int i;
for (i = 0; i < Fib_until i++) {
data[i] = i;
Req[i].data = (void *) &data[i];
Uv_queue_work (Loop, &req[i], fib, AFTER_FIB);
}
Return Uv_run (loop, uv_run_default);
The function uv_queue_work is defined as follows:
Uv_extern int Uv_queue_work (uv_loop_t* loop,
uv_work_t* req,
uv_work_cb WORK_CB,
UV_AFTER_WORK_CB AFTER_WORK_CB);