preface

For us front-end engineers, mastering Node.js application development is a necessary step towards becoming a senior/expert. Node.js is a server-side language, so not only should we be able to accomplish development tasks, but we should also focus on server performance.

This article gives a preliminary introduction to the basics and performance metrics of Node.js 👉.

Application scenarios

Before introducing NodeJS performance metrics, let’s take a look at its application scenarios. Different application scenarios have different performance metrics to focus on.

  1. The BFF middle layer, a proxy for interfaces, acts as the gateway layer

  2. Development build tools gulp, webpack based on Node.js

  3. The desktop application Electron is combined with Node.js

  4. SSR server rendering

If Node.js is used for front-end SSR, then CPU and network are the main performance bottlenecks;

If NodeJS is used for data persistence related work, I/O and disk usage will be high;

In most scenarios, CPU, memory, and network are the main performance bottlenecks for Node.

The advantages and disadvantages

  • Node.js is fault tolerant and does not perform very well

  • Node.js is not a professional database operator

  • Node.js handles asynchronous I/O strength

  • IO intensive, not suitable for CPU intensive

Event loop (LiBUV)

Here is a diagram from the official website that shows a simplified overview of the order in which the event loop operates

By describing

  • The timer: This phase has been executedsetTimeout() 和 setInterval()The scheduling callback function of.
  • Pending callback: An I/O callback that is deferred until the next iteration of the loop.
  • Idle, prepare: used only in the system.
  • polling: Retrieves new I/O events; Perform I/ O-related callbacks (in almost all cases, except for closed callback functions, those made by timers andsetImmediate()Out of schedule), the rest of the case node will block at this point in due course.
  • detection:setImmediate()This is where the callback function is executed.
  • The closed callback function: Some closed callback functions such as:socket.on('close', ...)

V8 GC mechanism

We know that Node.js® is a JavaScript runtime environment based on the Chrome V8 engine, which is also single-threaded.

V8 memory is divided into new generation and old generation:

New generation: Use the From space ->to space memory reclamation scavenge algorithm

Old generation: memory reclamation in the form of reference marking and defragmentation

If GC takes too long, js threads will block, affecting service performance. If the memory is used improperly, memory overflow may occur. With the basics of Node.js behind us, let’s look at performance metrics

Performance indicators

We describe a performance indicator at the system level and node.js process level

The system level

For servers (dedicated machines, VMS, and Dockers), the following monitoring indicators are provided:

  • Memory usage

  • CPU utilization

  • System load, number of processes in use/waiting

  • System QPS

  • Hard performance index

  • Disk usage

  • The GC statistics

The process level

For each Node.js process, the following monitoring indicators are provided:

  • In-heap (total and used) and out-of-heap memory statistics

  • Statistics on the memory occupied by each memory space in the heap

  • Garbage collection (GC) as a percentage of total process running time

  • QPS

  • Statistics are collected by CPU of 1s, 15s, 30s, and 60s

  • Libuv handle, timer statistics

How to get

How do we get the performance metrics mentioned above?

The system level

You can obtain system-level indicators in either of the following ways

  1. OS module
const os = requie('os')
Copy the code

Code sample

The execution result

  1. The top and iostat commands view memory and disk usage

Top [parameter]

Iostat (parameters)

Memory usage

// this method returns the node.js process memoryUsage object process.memoryusage ()Copy the code

Code sample

Execution Result:

{
  rss: 4935680,
  heapTotal: 1826816,
  heapUsed: 650472,
  external: 49879
}
Copy the code

Noun explanation:

RSS is the resident set size and how much physical memory has been allocated to the process (as a percentage of the total allocated memory)

As this metric increases, a memory leak may occur

HeapTotal and heapUsed represent V8 memory usage.

External represents the memory usage of C++ objects bound to Javascript that are managed by V8.

CPU profile

Generally speaking, heap snapshots can be taken if there is a memory leak involved, and CPU profiles can be taken if there is an abnormally high CPU

You can obtain it in either of the following ways:

GC trace

V8 provides a number of node.js startup options, and the following example code can be used to retrieve GC log information

Node — Result of trace_GC execution

You can see that V8 uses a different GC process for old and new memory

Memory snapshot

If you use Node-Inspector, there will be front-end variable interference in the snapshot. You are advised to use heapdump to save memory snapshots and devtool to view memory snapshots. When heapdump is used to save memory snapshots, only objects in the Node.js environment are present and not disturbed. The use of Heapdump will be described later

Pressure test

Before a project goes live, a stress test is conducted to find out if there are memory leaks

Pressure measurement tools: AB test (ApacheBench), Autocannon

The results of a stress test using the AB feature are shown below

The above results can be seen

One of our QPS: 4301.28/ SEC

Average duration per request: 23ms

Transfer rate: 617.47 KB /s

A memory leak

Node.js is relatively professional back-end language Java, PHP, etc., some basic construction is relatively not perfect. Coupled with the single-threaded feature, in large applications, it is easy to cause performance bottlenecks in the server or Node.js process.

Node memory leaks are usually caused by the following three situations:

  • Node V8’s internal memory size limits: 1.4GB for 64-bit systems and 0.7GB for 32-bit systems.

  • Program misuse: global variable references, improper closure use, event listeners not destroyed

  • Large file applications: Buffer should be used. Buffer does not take up V8 memory

So how do you troubleshoot memory leaks? You can use the following tools

Tool use

Heapdump: generates memory snapshot and chrome panel analysis

Note that printing a memory snapshot consumes a lot of CPU and may affect online services.

The introduction of

const heapdump = require('heapdump')
Copy the code

To obtain

Method 1: Run kill -usr2

Method 2: Call writeSnapshot

heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot');
Copy the code

Chrome Panel Analysis

2. Alinode

Ali Cloud also provides the performance platform Alinode for Nodejs applications, which can easily and comprehensively collect performance index data for us and make it more intuitive in the way of visual charts. Access to Alinode can be found in 5-minute Quick Start

The following is a chart showing part of the collected data

Some indicators description

Memory

  • memory_sys: percentage of system memory usage.
  • memory_node: Percentage of system memory used by all Node.js processes.

CPU

  • cpu_sys: indicates the percentage of system CPU usage.
  • cpu_node: Sum of CPU usage percentages of all Node.js processes.

Load

  • Load1: indicates the average Load within 1 minute.

  • Load5: indicates the average Load within 5 minutes.

  • Load15: indicates the average Load within 15 minutes.

  • Here are some references to Load (Load has been normalized, if it is an N-core CPU, then Load * N) :

    • 0.7 < Load < 1: Good state, can handle new tasks in a timely manner;
    • Load = 1: There are upcoming tasks that require extra waiting time to be processed and need attention.
    • Load > 5: Tasks require long wait times and require intervention.
    • Often see firstload15If it is high, look againload1 和 load5To see if there is a downward trend in the short termload1Greater than 1. Don’t worry if it takes a long timeLoadHigh, need to cause concern.

QPS

Total number of HTTP requests processed per second by all Node.js processes of this instance.

GC

  • gc_avg: Average garbage collection time of all Node.js processes.
  • gc_max: Percentage of the node.js process that takes the most garbage collection time per minute.

Open source Easy-Monitor

Enterprise Node.js application performance monitoring and online fault location solution.

Easy-monitor is a lightweight Node performance monitoring tool. Quick entry

We can also build on this foundation to deploy our own internal performance platform.

conclusion

Above is my brief introduction to Node.js performance metrics and capture, but more of an overview of performance points, each of which we can explore in more depth. I hope this article helped you, and thank you for reading. I look forward to seeing you soon

reference

How does the Node.js performance platform analyze memory leaks in Node.js