Node.js processes and threads

Advantages and disadvantages of single thread

1. PHP model

2. Node.js model

3. Node.js features
  • A high performance

Avoid the overhead of frequently creating and switching threads, making the execution faster; Small resource footprint, no need to create a thread model for each request and thus consume memory;

  • Thread safety

There is no need to worry about the same variable being read/written by multiple threads at the same time, resulting in program crash; It eliminates the tragedy caused by forgetting to lock or unlock variables in multi-threaded programming;

  • Asynchronous and non-blocking

Node.js is multithreaded at the bottom to access I/O;

  • Blocked single thread

When a lot of computation is required, other requests wait to be executed.

  • Single thread vs. multi-core

Thread is the basic unit of CPU scheduling. A CPU can only execute tasks of one thread at a time. If the machine running Node.js has a multi-core CPU like i5 or I7, the performance of the multi-core CPU cannot be fully utilized to serve Node.js.

Two, multithreading

1. Tagg2 module

Tagg2 allows Node.js to support multi-threaded development. It creates child threads through tagg2, and throws large parts of computation into the child threads to ensure the ease of the main thread of Node.js. When the child thread completes its task execution, the callback function of the main thread will be executed.

var express = require('express');
var tagg2 = require("tagg2");
var app = express();
var th_func = function(){// The thread executes the function, and the following is executed in the thread
    var fibo =function fibo (n) {// Define the fiBO function in the child thread
           return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
        }
    var n = fibo(~~thread.buffer);// Perform fiBO recursion
    thread.end(n);// When the thread finishes executing, thread.end calls back to the main thread with the result of the calculation
};
app.get('/'.function(req, res){
    var n = ~~req.query.n || 1;// Get user request parameters
    var buf = new Buffer(n.toString());
    tagg2.create(th_func, {buffer:buf}, function(err,result){
    // Create a js thread, passing in the worker function,buffer argument, and callback function
        if(err) return res.end(err);// If thread creation fails
        res.end(result.toString());// The response thread executes the result of the calculation})}); app.listen(8124);
Copy the code
V8 engine

The Tagg2 package uses the Phtread library and V8’s V8 ::Isolate Class to implement JS multithreading.

The Isolate represents a separate v8 engine instance. The V8 Isolate has a completely separate state. Objects in one Isolate instance cannot be used in another Isolate instance. Embedded developers can create additional Isolate instances in other threads to run in parallel. An Isolate instance can only be accessed by one thread at any one time and can be synchronized using lock/unlock.

As a result, we cannot access JS variables in multiple threads during v8 embedded development. This rule will directly cause the functions executed by threads in our previous tagg2 not to use the core API of Node.js, such as fs, crypto and other modules.

The Tagg2 package has its limitations. It can be used for large computations or loops that can use JS native. The Node.js core API cannot share object relationships from the main thread, so it cannot be used across threads.

3, libuv

Libuv is a cross-platform asynchronous I/O library for Node.js, including Event loops, Filesystem, Networking support, Threads, and Processes. Utilities Other tools.

Asynchronous multithreading in node.js core API is mostly implemented using Libuv.

Second, multiple processes

In html5 browsers, we can use Webworker to throw some time-consuming calculations into the worker process for execution, so that the main process will not be blocked and users will not feel stuck.

Webworker effects can also be achieved in Node.js using the Child_process module in the core API of Node.js. The child_process module provides a fork method, which can start a Node.js file as a worker process. When the worker process finishes working, it sends the result to the main process via send method, and then exits automatically.

  • app.js
var express = require('express');
var fork = require('child_process').fork;
var app = express();
app.get('/'.function(req, res){
  var worker = fork('./work_fibo.js') // Create a worker process
  worker.on('message'.function(m) {// Receive the result of the worker process calculation
          if('object'= = =typeof m && m.type === 'fibo'){
                   worker.kill();// Send a signal to kill the process
                   res.send(m.result.toString());// Return the result to the client}}); worker.send({type:'fibo'.num:~~req.query.n || 1});
  // Send to the worker process to calculate the number of FIBos
});
app.listen(8124);
Copy the code
  • work_fibo.js
var fibo = function fibo (n) {// Define the algorithm
   return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
}
process.on('message'.function(m) {
// Receive a message from the main process
          if(typeof m === 'object' && m.type === 'fibo') {var num = fibo(~~m.num);
                  / / calculate jibo
                  process.send({type: 'fibo'.result:num})
                  // Return the result after calculation}}); process.on('SIGHUP'.function() {
        process.exit();// The process exits after receiving the kill message
});
Copy the code

The main thread’s kill method does not actually exit the child, but rather triggers its SIGHUP event, again relying on process.exit().