Как предотвратить утечки памяти в node.js? - PullRequest
44 голосов
/ 20 апреля 2011

Мы знаем, что node.js дает нам большую мощь, но с большой властью приходит большая ответственность.

Насколько я знаю, движок V8 не выполняет сборку мусора. Итак, каковы наиболее распространенные ошибки, которых мы должны избегать, чтобы не допустить утечки памяти с моего сервера узлов.

EDIT: Извините за мое невежество, у V8 действительно есть мощный сборщик мусора.

Ответы [ 3 ]

65 голосов
/ 20 апреля 2011

Насколько я знаю, двигатель V8 не делать любую сборку мусора.

V8 имеет мощный и интеллектуальный сборщик мусора в сборке.

Ваша основная проблема не в понимании того, как замыкания поддерживают ссылку на контекст и контекст внешних функций. Это означает, что есть разные способы создания циклических ссылок или других переменных, которые просто очищают , а не .

Это потому, что ваш код неоднозначен и компилятор не может определить, безопасен ли он для сбора мусора.

Способ заставить GC собирать данные - обнулить ваши переменные.

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

Как v8 узнает, безопасно ли собирать мусор с большого объекта, когда он находится в обработчике событий? Это не так, вам нужно сказать, что он больше не используется, установив переменную в null.

Различные статьи для чтения:

23 голосов
/ 04 мая 2013

Я хотел убедиться в принятом ответе, а именно:

не понимая, как замыкания поддерживают ссылку на контекст и контекст внешних функций.

Итак, я написал следующий код, чтобы продемонстрировать, как переменные могут быть не очищены, что может заинтересовать людей.

Если у вас watch -n 0.2 'ps -o rss $(pgrep node)' работает в другом терминале, вы можете наблюдать утечку. Обратите внимание, что комментирование в buffer = 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');
    });

}());
8 голосов
/ 18 марта 2015

активный сборщик мусора:

node --expose-gc test.js

и использование с:

global.gc();

Happy Coding:)

...