Выполнение сбора мусора вручную в node

Я использую node и рассматриваю возможность ручной работы с сборкой мусора в node. Есть ли недостатки в этом? Причина, по которой я делаю это, состоит в том, что похоже, что node недостаточно работает с сборкой мусора. Кто-нибудь знает, как часто V8 выполняет свою процедуру сбора мусора в node?

Спасибо!

Ответ 1

У меня на самом деле была проблема с node на герою с экземплярами 1 ГБ.

При запуске сервера node на производственном трафике память будет расти постоянно, пока не превысит ограничение на память, что заставило его работать медленно.

Вероятно, это связано с тем, что приложение генерирует много мусора, оно в основном обслуживает ответы JSON API. Но это была не утечка памяти, а просто несохраненный мусор.

Похоже, что node не уделяет приоритетное внимание выполнению достаточных коллекций мусора на старом объекте для моего приложения, поэтому память будет постоянно расти.

Запуск global.gc() вручную (с поддержкой node --expose_gc) уменьшит использование памяти на 50 МБ каждый раз и приостанавливает приложение примерно на 400 мс.

То, что я закончил, запускает gc вручную в рандомизированном расписании (так что экземпляры heroku не будут делать GC все сразу). Это уменьшило использование памяти и остановило превышение квоты памяти.

Упрощенная версия будет примерно такой:

function scheduleGc() {
  if (!global.gc) {
    console.log('Garbage collection is not exposed');
    return;
  }

  // schedule next gc within a random interval (e.g. 15-45 minutes)
  // tweak this based on your app memory usage
  var nextMinutes = Math.random() * 30 + 15;

  setTimeout(function(){
    global.gc();
    console.log('Manual gc', process.memoryUsage());
    scheduleGc();
  }, nextMinutes * 60 * 1000);
}

// call this in the startup script of your app (once per process)
scheduleGc();

Вам нужно запустить приложение с выставленной сборкой мусора:

node --expose_gc app.js

Ответ 2

Я знаю, что это может быть немного запоздалый ответ, чтобы помочь OP, но я думал, что буду сотрудничать с моим недавним опытом с распределением памяти Node JS и сбором мусора.

В настоящее время мы работаем над сервером Node JS, работающим на малине pi 3. Каждый так часто он вылетает из-за нехватки памяти. Первоначально я думал, что это утечка памяти, и после полутора недель поиска моего кода и ничего не придумал, я подумал, что проблема может быть усугублена тем фактом, что Node JS выделяет больше памяти, чем доступно на Rpi3 для своих процессов до того, как он выполнит GC.

Я запускал новые экземпляры своего сервера со следующими командами:

'node server.js --max-executable-size = 96 -max-old-space-size = 128 -max-semi-space-size = 2'

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

РЕДАКТИРОВАТЬ: Эта ссылка здесь более конкретно описывает проблему, с которой я имел дело.

- nodejs уменьшает использование памяти коллектора мусора v8 - https://github.com/nodejs/node/issues/2738

Ответ 3

V8 Запускайте сборку мусора, когда он считает это интересным. Для этого нет фиксированной задержки. Вы можете прочитать эту статью, чтобы узнать о сборке мусора V8: https://strongloop.com/strongblog/node-js-performance-garbage-collection/

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