Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Heap memory allocation in Node

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail the example analysis of heap memory allocation in Node. Xiaobian thinks it is quite practical, so share it with you as a reference. I hope you can gain something after reading this article.

Introduction to V8 Garbage Collection

First of all, let's briefly introduce the V8 garbage collector. Memory is allocated in a heap, which is divided into several generational regions. As an object ages throughout its life cycle, it belongs to a different generation.

Generations are divided into younger and older generations, while younger generations are divided into new and middle generations. As objects survive garbage collection, they also join older generations.

The basic principle of the generation hypothesis is that most subjects are young. The V8 garbage collector is based on this and promotes only objects that survive garbage collection. As objects are copied into adjacent regions, they eventually move into older generations.

Memory consumption in Nodejs is divided into three main aspects:

Code-Where the code is executed

Call Stack-Used to store functions and local variables with primitive types (numeric, string, or Boolean)

heap memory

Heap memory is our main focus today. Now that you know more about garbage collectors, it's time to allocate some memory on the heap!

function allocateMemory(size) { // Simulate allocation of bytes const numbers = size / 8; const arr = []; arr.length = numbers; for (let i = 0; i

< numbers; i++) { arr[i] = i; } return arr;} 在调用栈中,局部变量随着函数调用结束而销毁。基础类型 number永远不会进入堆内存,而是在调用栈中分配。但是对象arr将进入堆中并且可能在垃圾回收中幸存下来。 堆内存有限制吗? 现在进行勇敢测试--将 Node 进程推到极限看看在哪个地方会耗尽堆内存: const memoryLeakAllocations = [];const field = "heapUsed";const allocationStep = 10000 * 1024; // 10MBconst TIME_INTERVAL_IN_MSEC = 40;setInterval(() =>

{ const allocation = allocateMemory(allocationStep); memoryLeakAllocations.push(allocation); const mu = process.memoryUsage(); // # bytes / KB / MB / GB const gbNow = mu[field] / 1024 / 1024 / 1024; const gbRounded = Math.round(gbNow * 100) / 100; console.log(`Heap allocated ${gbRounded} GB`);}, TIME_INTERVAL_IN_MSEC);

In the code above, we allocated about 10 mb at 40 ms intervals, giving garbage collection enough time to promote surviving objects to older ages. Process.memoryUsage is a tool for recovering rough metrics about heap utilization. As the heap allocation grows, the heapUsed field records the heap size. This field records the number of bytes in RAM, which can be converted to mb.

Your results may be different. A Windows 10 laptop with 32GB of memory will get the following results:

Heap allocated 4 GBHeap allocated 4.01 GB[18820:000001A45B4680A0] 26146 ms: Mark-sweep (reduce) 4103.7 (4107.3) -> 4103.7 (4108.3) MB, 1196.5 / 0.0 ms (average mu = 0.112, current mu = 0.000) last resort GC in old space requestedFATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

Here, the garbage collector will try to compact memory as a last resort, giving up and throwing an "out of heap memory" exception. This process reaches the 4.1GB limit and takes 26.6 seconds to realize that the service is going to hang up.

Some of the reasons for these results are unknown. The V8 garbage collector initially ran in a 32-bit browser process with strict memory constraints. These results suggest that memory limitations may have been inherited from legacy code.

At the time of writing, the above code is running under the latest LTS version of Node and using a 64-bit executable file. Theoretically, a 64-bit process should be able to allocate more than 4 GB of space and easily grow to 16 TB of address space.

Expand memory allocation limits node index.js --max-old-space-size=8000

This sets the maximum limit to 8GB. Be careful when doing this. My laptop has 32GB of space. I recommend setting it to the actual space available in RAM. Once physical memory runs out, processes start consuming disk space through virtual memory. If you set the limit too high, you get a new reason to change computers. Here we try to avoid smoking.

Let's run the code again with the 8GB limit:

Heap allocated 7.8 GBHeap allocated 7.81 GB[16976:000001ACB8FEB330] 45701 ms: Mark-sweep (reduce) 8000.2 (8005.3) -> 8000.2 (8006.3) MB, 1468.4 / 0.0 ms (average mu = 0.211, current mu = 0.000) last resort GC in old space requestedFATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

This time the heap size was almost 8GB, but not quite there. I suspect there is some overhead in the Node process to allocate so much memory. This process takes 45.7 seconds to complete.

In a production environment, memory may run out in no less than a minute. This is one of the reasons monitoring and insight into memory consumption helps. Memory consumption grows slowly over time and it may take days to know that there is a problem. If the process keeps crashing and the "out of heap memory" exception appears in the log, there may be a memory leak in the code.

A process may also consume more memory because it is processing more data. If resource consumption continues to grow, it may be time to break down this monolith into microservices. This reduces memory pressure on individual processes and allows nodes to scale horizontally.

How to Track Node.js Memory Leaks

The heapUsed field of process.memoryUsage is still somewhat useful, and one way to debug memory leaks is to put memory metrics in another tool for further processing. Since this implementation is not complicated, it is mainly analyzed how to implement it yourself.

const path = require("path");const fs = require("fs");const os = require("os");const start = Date.now ();const LOG_FILE = path.join(__dirname, "memory-usage.csv");fs.writeFile(LOG_FILE, "Time Alive (secs),Memory GB" + os.EOL, () => {}); //please-verify

To avoid putting heap allocation metrics in memory, we chose to write the results to a CSV file for easy data consumption. The writeFile asynchronous function with callback is used here. Callback empty to write file and continue without any further processing. To get progressive memory metrics, add them to console.log:

const elapsedTimeInSecs = (Date.now() - start) / 1000;const timeRounded = Math.round(elapsedTimeInSecs * 100) / 100;s.appendFile(LOG_FILE, timeRounded + "," + gbRounded + os.EOL, () => {}); //please-confirm

The above code can be used to debug memory leak situations where heap memory grows over time. You can use some analysis tools to parse native csv data to achieve a nice visualization.

If you are just in a hurry to see the data, you can also use Excel directly, as shown below:

With a limit of 4.1GB, you can see that memory usage increases linearly over a short period of time. Memory consumption continues to grow and does not level off, indicating that there is a memory leak somewhere. As we debug this type of problem, we look for the part of the code that was distributed at the end of the old generation.

Objects that survive garbage collection may persist until the process terminates.

One way to make this memory leak detection code more reusable is to wrap it in its own time interval (since it doesn't have to be in the main loop).

setInterval(() => { const mu = process.memoryUsage(); // # bytes / KB / MB / GB const gbNow = mu[field] / 1024 / 1024 / 1024; const gbRounded = Math.round(gbNow * 100) / 100; const elapsedTimeInSecs = (Date.now() - start) / 1000; const timeRounded = Math.round(elapsedTimeInSecs * 100) / 100; fs.appendFile(LOG_FILE, timeRounded + "," + gbRounded + os.EOL, () => {}); // fire-and-forget}, TIME_INTERVAL_IN_MSEC);

Note that these methods are not directly applicable to production environments, but merely show you how to debug memory leaks locally. The actual implementation also includes automatic displays, alerts, and rotating logs so that the server does not run out of disk space.

Tracking Node.js memory leaks in production environments

Although the above code is not feasible in a production environment, we have seen how to debug memory leaks. Therefore, as an alternative, you can wrap the Node process in a daemon such as PM2.

Set restart policy when memory consumption reaches limit:

pm2 start index.js --max-memory-restart 8G

Units can be K (kilobytes), M (megabytes), and G (gigabytes). Process restart takes approximately 30 seconds, so configure multiple nodes through a Load Balancer to avoid outages.

Another nifty tool is the cross-platform native module node-memwatch, which triggers an event when it detects a memory leak in running code.

const memwatch = require("memwatch");memwatch.on("leak", function (info) { // event emitted console.log(info.reason);}); copy code

The event is triggered by a leak, and its callback object has a reason that grows as the continuous garbage collection heap grows.

Diagnosing memory limitations using AppSignal's Magic Dashboard

AppSignal has a magic dashboard for monitoring garbage collection statistics for heap growth.

The image above shows that the request stopped for seven minutes around 14:25, allowing garbage collection to reduce memory stress. Dashboards are also exposed when objects stay in old space for too long and cause memory leaks.

About "Node heap memory allocation example analysis" This article is shared here, I hope the above content can be of some help to everyone, so that you can learn more knowledge, if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report