Подтвердить что ты не робот

Как работает сборщик мусора Node.js(v8)?

Я провел несколько тестов с моим приложением node.js, который искал утечку памяти, которую должен выполнять мой код. Я запускаю script, который, на мой взгляд, должен утечка памяти, но я удивлен результатом.

redisClient.on('message', initRequest);


function onSuccess(self, json){

  console.dir(json);

}


function initRequest(channel, message){

  var request = new RequestObject({

    redisMessage: message

  });

  request.on('success', onSuccess);

}

redisClient испускает пару событий сообщения в секунду. Это означает, что функция initRequest вызывается довольно часто. Каждый раз, когда объект request создается в памяти, а функция onSuccess привязывается к событию "success".

Я предположил (но здесь я могу ошибаться), что, поскольку в этом случае есть слушатель (onSuccess), привязка к этому объекту не может быть собрана мусором. Тогда я подумал, что использование памяти будет расти, поскольку память не будет бесплатной.

В качестве решения этой потенциальной утечки я хотел использовать .once вместо .on, так как это приведет к отключению слушателя, и объект может быть собран в мусор.

Я использовал pmap для тестирования обоих сценариев (сравнение .on и .once и другого сценария, о котором здесь не стоит упоминать), и я не нашел большой разницы.

enter image description here

Подводя итог, у меня есть 2 вопроса:

  • Является ли это обычным поведением GC для очистки памяти через определенные промежутки времени или после того, как он достигнет некоторого threashold вместо непрерывной очистки?

  • Я правильно предполагаю, что код примера с .on должен протекать в памяти, которую я не вижу на графике потребления памяти?

4b9b3361

Ответ 1

1: да: -)

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

Итак, в вашем коде функция onSuccess будет ссылаться на ваш объект request. Однако, onSuccess - это только одна функция, которая повторно используется как слушатель для всех объектов запроса, поэтому это не должно приводить к накоплению памяти.

Sidenote: я не знаю внутренности redisClient и RequestObject, но для меня также выглядит, что request будет готов к сборке мусора, как только функция initRequest завершится, то есть, возможно, прежде чем кто-либо из его слушателей будет вызван.

Ответ 2

Насколько я вижу, объект запроса должен существовать только внутри функции initRequest и должен быть помечен для сбора мусора, когда функция завершается.