Introduction of some methods to give full play to Node.js program performance

Source: Internet
Author: User
Tags advantage

This article mainly introduces some methods to give full play to the performance of Node.js program, Node.js is to use JavaScript for server-side framework, the need for friends can refer to the

A node.js process will only run on a single physical core, which is why you need to pay extra attention when developing scalable servers.

There are many different ways to design a node.js that can be used in parallel, because there are a series of stable APIs, plus the development of native extensions to manage processes. In this blog post, we'll compare these possible architectures.

This article also introduces the Compute-cluster module: a small node.js library that can be used to facilitate the management process, and never second-line distributed computing.

Problems encountered

We need to be able to handle a large number of different features in the Mozilla Persona project, so we try to use Node.js.

In order not to affect the user experience, the ' Interactive ' request we designed requires only lightweight computational consumption, but provides a faster response time that makes the UI less jammed. By contrast, the ' Batch ' operation takes approximately half a second of processing time, and may have a longer delay for other reasons.

To better design, we find a lot of ways to meet our current needs to solve.

Given the scalability and cost, we list the following key requirements:

Efficiency: Efficient Use of all idle processors

Response: Our "apps" can respond quickly and in real time

Elegance: When the volume of requests is too high to handle, we deal with what we can handle. Can not handle the need to clear the error feedback

Simple: Our solution must be simple and easy to use

Through the above points we can clear, targeted to screen

Solution one: Directly in the main thread process.

When the main thread processes data directly, the results are bad:

You can't take advantage of multi-core CPUs, and in an interactive request/response, you have to wait for the current request (or response) to be processed, with no grace whatsoever.

The only advantage of this scheme is that it's simple enough

?

1

2

3

4function Myrequesthandler (Request, response) [

Let's bring everything to a grinding halt for half a second.

var results = Docomputationworksync (Request.somesuch);

}

In the Node.js program, you want to handle multiple requests at the same time, and want to synchronize processing, then you are ready to make a mess.

Method 2: Whether to use asynchronous processing.

Is there a lot of performance improvement if you use asynchronous methods in the background?

The answer is not necessarily. It depends on whether the background operation is meaningful

For example, if you are using JavaScript on the main thread or local code to compute, performance is no better than synchronous processing, you do not need to use asynchronous methods in the background to deal with

Please read the following code

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16function docomputationwork (input, callback) {

Because the internal implementation of this asynchronous

The function is itself synchronously run on the main thread,

You still starve the entire process.

var output = Docomputationworksync (input);

Process.nexttick (function () {

Callback (null, output);

});

}

function Myrequesthandler (request, response) [

Even though this *looks* better, we ' re still bringing

To a grinding halt.

Docomputationwork (Request.somesuch, function (err, results) {

... do something with results ...

});

}

The key point is that the use of Nodejs asynchronous APIs does not depend on the application of multiple processes

Scheme three: Using line threading to realize asynchronous processing.

As long as it is implemented properly, libraries that use local code implementations can break through the restrictions to achieve multi-threaded functionality when Nodejs calls.

There are many such examples, the Bcrypt library that Nick Campbell wrote is one of the best.

If you take this library for a test on a 4-core machine, you'll see the magic scene: 4 times times the usual throughput and exhausting almost all the resources! But if you test on a 24-core machine, the results will not change much: There are 4 core usage rates that are roughly 100%. But the rest of the core is largely idle.

The problem is that the library uses a thread pool within the Nodejs, and this thread pool is not suitable for this kind of computation. In addition, this thread pool cap is written dead and can run up to 4 threads.

In addition to writing dead caps, the deeper reason for this problem is:

Using the NODEJS internal thread pool for a large number of operations can hinder its file or network operations and make the program appear to respond slowly.

It's hard to find the right way to deal with waiting queues: Imagine if you had a 5-minute backlog of threads in your queue, would you like to continue adding threads to it?

In this case, the component library of the built-in threading mechanism can not effectively utilize the advantages of multi-core, which reduces the response ability of the program, and the program performance becomes worse with the increase of load.

Scenario four: Using the Nodejs cluster module

The Nodejs 0.6.x version provides a cluster module that allows you to create a set of processes that share the same socket to share load pressures.

What would happen if you adopted the above scheme and used the cluster module at the same time?

The resulting scheme will have the same drawbacks as synchronous processing or built-in thread pooling: slow response, no elegance to speak of.

Sometimes, just adding a new run instance does not solve the problem.

Programme V: Introduction of Compute-cluster Modules

In persona, our solution is to maintain a single set of functional (but not all) computational processes.

In this process, we wrote the Compute-cluster library.

This library automatically starts and manages the subprocess on demand, so that you can use the code to process the data in a cluster of local child processes.

Use examples:

?

1

2

3

4

5

6

7

8

9

10

11

12const Computecluster = require (' Compute-cluster ');

Allocate a COMPUTE Cluster

var cc = new Computecluster ({module: './worker.js '});

Run work in parallel

Cc.enqueue ({input: "foo"}, function (error, result) {

Console.log ("foo done", result);

});

Cc.enqueue ({input: "bar"}, function (error, result) {

Console.log ("Bar done", result);

});

The message event is responded to in Fileworker.js, and the incoming request is processed:

?

1

2

3

4

5

6

7process.on (' message ', function (m) {

var output;

Do lots of work here, and we don ' t care that we ' re blocking the

Main thread because this process was intended to does one thing at a time.

var output = Docomputationworksync (M.input);

Process.send (output);

});

Without changing the calling code, the Compute-cluster module can be integrated with the existing asynchronous APIs so that real multi-core parallel processing can be exchanged with minimal code.

Let's look at the performance of this program from four aspects.

Multi-core parallel capability: The subprocess uses all of the core.

Responsiveness: Because the core management process is only responsible for initiating subprocess and delivering messages, it is idle for most of the time and can handle more interaction requests.

Even if the load pressure on the machine is very high, we can still use the scheduler of the operating system to improve the priority of the core management process.

Simplicity: Using the asynchronous API to hide the details of the implementation, we can easily integrate the module into the current project, even the calling code does not need to be changed.

Now let's see if we can find a way to reduce the efficiency of the system even if the load suddenly surges.

The best goal, of course, is still that the system can operate efficiently and handle as many requests as possible, even if the pressure surges.

To help achieve good scenarios, compute-cluster not only manages child processes and delivers messages, it also manages other information.

It records the number of child processes currently running and the average time that each child process completes.

With these records, we can predict how long it will take before the child process is opened.

With this, plus the user-set parameters (Max_request_time), we can simply turn off requests that might be timed out without being processed.

This feature makes it easy to determine your code based on the user experience. For example, "Users should not wait more than 10 seconds to log in." "This is probably equivalent to setting Max_request_time to 7 seconds (you need to consider network transmission time)."

The results of our stress tests on the persona service were satisfying.

Under high pressure, we are still able to provide services to authenticated users, block a subset of users who are not authenticated, and display related error messages.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.