如何防止node.js中的内存泄漏?

时间:2021-11-24 20:28:05

We know node.js provides us with great power but with great power comes great responsibility.

我们知道节点。js为我们提供了巨大的力量,但也带来了巨大的责任。

As far as I know the V8 engine doesn't do any garbage collection. So what are the most common mistakes we should avoid to ensure that no memory is leaking from my node server.

据我所知,V8引擎不做任何垃圾收集。因此,我们应该避免的最常见错误是什么,以确保没有内存从节点服务器泄漏。

EDIT: Sorry for my ignorance, V8 does have a powerful garbage collector.

编辑:为我的无知感到抱歉,V8确实有一个强大的垃圾收集器。

4 个解决方案

#1


62  

As far as I know the V8 engine doesn't do any garbage collection.

据我所知,V8引擎不做任何垃圾收集。

V8 has a powerful and intelligent garbage collector in build.

V8在build中有一个强大而智能的垃圾收集器。

Your main problem is not understanding how closures maintain a reference to scope and context of outer functions. This means there are various ways you can create circular references or otherwise create variables that just do not get cleaned up.

您的主要问题是不理解闭包如何维护对外部函数范围和上下文的引用。这意味着有多种方法可以创建循环引用或创建变量,这些变量不会被清理。

This is because your code is ambigious and the compiler can not tell if it is safe to garbage collect it.

这是因为您的代码非常复杂,编译器无法判断垃圾收集它是否安全。

A way to force the GC to pick up data is to null your variables.

强制GC获取数据的一种方法是使变量为空。

function(foo, cb) {
    var bigObject = new BigObject();
    doFoo(foo).on("change", function(e) {
         if (e.type === bigObject.type) {
              cb();
              // bigObject = null;
         }
    });
}

How does v8 know whether it is safe to garbage collect big object when it's in an event handler? It doesn't so you need to tell it it's no longer used by setting the variable to null.

v8如何知道在事件处理程序中垃圾收集大对象是否安全?它没有,所以你需要告诉它它不再被使用通过将变量设置为null。

Various articles to read:

各种文章阅读:

#2


20  

I wanted to convince myself of the accepted answer, specifically:

我想说服自己接受的答案,特别是:

not understanding how closures maintain a reference to scope and context of outer functions.

不了解闭包如何维护对外部函数范围和上下文的引用。

So I wrote the following code to demonstrate how variables can fail to be cleaned up, which people may find of interest.

因此我编写了下面的代码来演示变量如何不能被清理,人们可能会对此感兴趣。

If you have watch -n 0.2 'ps -o rss $(pgrep node)' running in another terminal you can watch the leak occurring. Note how commenting in either the buffer = null or using nextTick will allow the process to complete:

如果您在另一个终端中看到- n0.2 'ps -o rss $(pgrep节点)'运行,您可以看到泄漏发生。注意,在缓冲区= null或使用nextTick时,注释将如何使进程完成:

(function () {
    "use strict";

    var fs = require('fs'),
        iterations = 0,

        work = function (callback) {
            var buffer = '',
                i;

            console.log('Work ' + iterations);

            for (i = 0; i < 50; i += 1) {
                buffer += fs.readFileSync('/usr/share/dict/words');
            }

            iterations += 1;
            if (iterations < 100) {
                // buffer = null;

                // process.nextTick(function () {
                    work(callback);
                // });
            } else {
                callback();
            }
        };

    work(function () {
        console.log('Done');
    });

}());

#3


7  

active garbage collection with:

活跃的垃圾收集:

node --expose-gc test.js

and use with:

和使用:

global.gc();

Happy Coding :)

编码快乐:)

#4


-2  

SBuffer v2 (static buffer) function is all you need to solve Node.js memory leaks, and it is very easy to use.

SBuffer v2(静态缓冲区)函数是解决节点所需的全部功能。js内存泄漏,非常容易使用。

npm install sbuffer

Example, allocate 2 buffers 300Mb each (600Mb total), and 300/10 (30Mb bytes) each for garbage use. In this way, your app will never grow in memory usage, because it's using only the allocated 600Mb memory space.

例如,为每个缓冲区分配300Mb(总共600Mb)和300/10 (30Mb字节)用于垃圾使用。这样,您的应用程序将永远不会在内存使用中增长,因为它只使用已分配的600Mb内存空间。

var SBuffer = require('sbuffer');

/* allocate 600Mb memory*/
var sb = SBuffer(2,3e8,10);

sb.t0 = '01';/* add a key t0 with string value 01 */

console.log(sb.t0);/* print: <Buffer 30 31> */
console.log(sb.t0.toString());/* print: 01 */

Input value type must be non-empty String or Buffer, and the output type is only Buffer or undefined if the key doesn't exists.

输入值类型必须是非空字符串或缓冲区,如果键不存在,则输出类型仅为缓冲区或未定义。

SBuffer add a nice functionality for your app from "scratch", but for those existing ones, you can only pray :)

SBuffer为你的应用程序添加了“scratch”功能,但对于现有的应用程序,你只能祈祷:)

#1


62  

As far as I know the V8 engine doesn't do any garbage collection.

据我所知,V8引擎不做任何垃圾收集。

V8 has a powerful and intelligent garbage collector in build.

V8在build中有一个强大而智能的垃圾收集器。

Your main problem is not understanding how closures maintain a reference to scope and context of outer functions. This means there are various ways you can create circular references or otherwise create variables that just do not get cleaned up.

您的主要问题是不理解闭包如何维护对外部函数范围和上下文的引用。这意味着有多种方法可以创建循环引用或创建变量,这些变量不会被清理。

This is because your code is ambigious and the compiler can not tell if it is safe to garbage collect it.

这是因为您的代码非常复杂,编译器无法判断垃圾收集它是否安全。

A way to force the GC to pick up data is to null your variables.

强制GC获取数据的一种方法是使变量为空。

function(foo, cb) {
    var bigObject = new BigObject();
    doFoo(foo).on("change", function(e) {
         if (e.type === bigObject.type) {
              cb();
              // bigObject = null;
         }
    });
}

How does v8 know whether it is safe to garbage collect big object when it's in an event handler? It doesn't so you need to tell it it's no longer used by setting the variable to null.

v8如何知道在事件处理程序中垃圾收集大对象是否安全?它没有,所以你需要告诉它它不再被使用通过将变量设置为null。

Various articles to read:

各种文章阅读:

#2


20  

I wanted to convince myself of the accepted answer, specifically:

我想说服自己接受的答案,特别是:

not understanding how closures maintain a reference to scope and context of outer functions.

不了解闭包如何维护对外部函数范围和上下文的引用。

So I wrote the following code to demonstrate how variables can fail to be cleaned up, which people may find of interest.

因此我编写了下面的代码来演示变量如何不能被清理,人们可能会对此感兴趣。

If you have watch -n 0.2 'ps -o rss $(pgrep node)' running in another terminal you can watch the leak occurring. Note how commenting in either the buffer = null or using nextTick will allow the process to complete:

如果您在另一个终端中看到- n0.2 'ps -o rss $(pgrep节点)'运行,您可以看到泄漏发生。注意,在缓冲区= null或使用nextTick时,注释将如何使进程完成:

(function () {
    "use strict";

    var fs = require('fs'),
        iterations = 0,

        work = function (callback) {
            var buffer = '',
                i;

            console.log('Work ' + iterations);

            for (i = 0; i < 50; i += 1) {
                buffer += fs.readFileSync('/usr/share/dict/words');
            }

            iterations += 1;
            if (iterations < 100) {
                // buffer = null;

                // process.nextTick(function () {
                    work(callback);
                // });
            } else {
                callback();
            }
        };

    work(function () {
        console.log('Done');
    });

}());

#3


7  

active garbage collection with:

活跃的垃圾收集:

node --expose-gc test.js

and use with:

和使用:

global.gc();

Happy Coding :)

编码快乐:)

#4


-2  

SBuffer v2 (static buffer) function is all you need to solve Node.js memory leaks, and it is very easy to use.

SBuffer v2(静态缓冲区)函数是解决节点所需的全部功能。js内存泄漏,非常容易使用。

npm install sbuffer

Example, allocate 2 buffers 300Mb each (600Mb total), and 300/10 (30Mb bytes) each for garbage use. In this way, your app will never grow in memory usage, because it's using only the allocated 600Mb memory space.

例如,为每个缓冲区分配300Mb(总共600Mb)和300/10 (30Mb字节)用于垃圾使用。这样,您的应用程序将永远不会在内存使用中增长,因为它只使用已分配的600Mb内存空间。

var SBuffer = require('sbuffer');

/* allocate 600Mb memory*/
var sb = SBuffer(2,3e8,10);

sb.t0 = '01';/* add a key t0 with string value 01 */

console.log(sb.t0);/* print: <Buffer 30 31> */
console.log(sb.t0.toString());/* print: 01 */

Input value type must be non-empty String or Buffer, and the output type is only Buffer or undefined if the key doesn't exists.

输入值类型必须是非空字符串或缓冲区,如果键不存在,则输出类型仅为缓冲区或未定义。

SBuffer add a nice functionality for your app from "scratch", but for those existing ones, you can only pray :)

SBuffer为你的应用程序添加了“scratch”功能,但对于现有的应用程序,你只能祈祷:)