Node.js куча нехватки памяти

Сегодня я запустил свой скрипт для индексации файловой системы, чтобы обновить индекс файлов RAID, и через 4 часа он вышел из строя со следующей ошибкой:

[md5:]  241613/241627 97.5%  
[md5:]  241614/241627 97.5%  
[md5:]  241625/241627 98.1%
Creating missing list... (79570 files missing)
Creating new files list... (241627 new files)

<--- Last few GCs --->

11629672 ms: Mark-sweep 1174.6 (1426.5) -> 1172.4 (1418.3) MB, 659.9 / 0 ms [allocation failure] [GC in old space requested].
11630371 ms: Mark-sweep 1172.4 (1418.3) -> 1172.4 (1411.3) MB, 698.9 / 0 ms [allocation failure] [GC in old space requested].
11631105 ms: Mark-sweep 1172.4 (1411.3) -> 1172.4 (1389.3) MB, 733.5 / 0 ms [last resort gc].
11631778 ms: Mark-sweep 1172.4 (1389.3) -> 1172.4 (1368.3) MB, 673.6 / 0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x3d1d329c9e59 <JS Object>
1: SparseJoinWithSeparatorJS(aka SparseJoinWithSeparatorJS) [native array.js:~84] [pc=0x3629ef689ad0] (this=0x3d1d32904189 <undefined>,w=0x2b690ce91071 <JS Array[241627]>,L=241627,M=0x3d1d329b4a11 <JS Function ConvertToString (SharedFunctionInfo 0x3d1d3294ef79)>,N=0x7c953bf4d49 <String[4]\: ,\n  >)
2: Join(aka Join) [native array.js:143] [pc=0x3629ef616696] (this=0x3d1d32904189 <undefin...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/bin/node]
 2: 0xe2c5fc [/usr/bin/node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [/usr/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/bin/node]
 5: v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [/usr/bin/node]
 6: v8::internal::Runtime_SparseJoinWithSeparator(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
 7: 0x3629ef50961b

Сервер оснащен 16 ГБ ОЗУ и 24 ГБ SSD подкачки. Я сильно сомневаюсь, что мой сценарий превысил 36 ГБ памяти. По крайней мере, это не должно

Скрипт создает индекс файлов, хранящихся в виде массива объектов с метаданными файлов (даты изменения, разрешения и т. Д., Без больших данных)

Вот полный код скрипта: http://pastebin.com/mjaD76c3

Я уже испытывал странные проблемы с узлами в прошлом с этим скриптом, что заставило меня, например. при работе с такими большими файлами, как String, индекс делился на несколько файлов, так как узел глючил. Есть ли способ улучшить управление памятью nodejs с огромными наборами данных?

42 ответа

Решение

Если я правильно помню, существует строгий стандартный предел использования памяти в V8 около 1,7 ГБ, если вы не увеличиваете его вручную.

В одном из наших продуктов мы использовали это решение в нашем сценарии развертывания:

 node --max-old-space-size=4096 yourFile.js

Также будет новая команда пробела, но, как я читал здесь: http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection, новое пространство собирает только недавно созданные краткосрочные данные, а старое пространство содержит все ссылочные структуры данных, которые должны быть в ваш случай лучший вариант.

Если вы хотите увеличить использование памяти узла глобально, а не только одним скриптом, вы можете экспортировать переменную среды, например:
export NODE_OPTIONS=--max_old_space_size=4096

Тогда вам не нужно играть с файлами при запуске сборок, как npm run build,

На всякий случай, если кто-то столкнется с этим в среде, где он не может установить свойства узла напрямую (в моем случае это инструмент сборки):

NODE_OPTIONS="--max-old-space-size=4096" node ...

Вы можете установить параметры узла с помощью переменной среды, если не можете передать их в командной строке.

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

1 ГБ - 8 ГБ

#increase to 1gb
node --max-old-space-size=1024 index.js

#increase to 2gb
node --max-old-space-size=2048 index.js 

#increase to 3gb
node --max-old-space-size=3072 index.js

#increase to 4gb
node --max-old-space-size=4096 index.js

#increase to 5gb
node --max-old-space-size=5120 index.js

#increase to 6gb
node --max-old-space-size=6144 index.js

#increase to 7gb
node --max-old-space-size=7168 index.js

#increase to 8gb 
node --max-old-space-size=8192 index.js 

Я только что столкнулся с той же проблемой с моим экземпляром EC2 t2.micro, который имеет 1 ГБ памяти.

Я решил проблему, создав файл подкачки с использованием этого URL-адреса и установив следующую переменную среды.

export NODE_OPTIONS=--max_old_space_size=4096

Наконец проблема ушла.

Я надеюсь, что это будет полезно в будущем.

Я боролся с этим даже после установки --max-old-space-size.

Тогда я понял, что нужно поставить опции --max-old-space-size перед сценарием кармы.

Также лучше всего указать оба синтаксиса --max-old-space-size и --max_old_space_size мой скрипт для кармы:

node --max-old-space-size=8192 --optimize-for-size --max-executable-size=8192  --max_old_space_size=8192 --optimize_for_size --max_executable_size=8192 node_modules/karma/bin/karma start --single-run --max_new_space_size=8192   --prod --aot

ссылка https://github.com/angular/angular-cli/issues/1652

Я столкнулся с этой проблемой при попытке отладки с помощью VSCode, поэтому просто хотел добавить, как вы можете добавить аргумент в настройку отладки.

Вы можете добавить его в runtimeArgs свойство вашего конфига в launch.json,

Смотрите пример ниже.

{
"version": "0.2.0",
"configurations": [{
        "type": "node",
        "request": "launch",
        "name": "Launch Program",
        "program": "${workspaceRoot}\\server.js"
    },
    {
        "type": "node",
        "request": "launch",
        "name": "Launch Training Script",
        "program": "${workspaceRoot}\\training-script.js",
        "runtimeArgs": [
            "--max-old-space-size=4096"
        ]
    }
]}

У меня была похожая проблема при выполнении угловых сборок AOT. Следующие команды помогли мне.

npm install -g increase-memory-limit
increase-memory-limit

Источник: https://geeklearning.io/angular-aot-webpack-memory-trick/

Я просто хочу добавить, что в некоторых системах, даже увеличивая предел памяти узла с помощью --max-old-space-size, этого недостаточно и возникает такая ошибка ОС:

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

В этом случае, вероятно, вы достигли максимального значения mmap для каждого процесса.

Вы можете проверить max_map_count, запустив

sysctl vm.max_map_count

и увеличить его, запустив

sysctl -w vm.max_map_count=655300

и исправьте его, чтобы он не сбрасывался после перезагрузки, добавив эту строку

vm.max_map_count=655300

в /etc/sysctl.conf файл.

Проверьте здесь для получения дополнительной информации.

Хороший метод анализа ошибки - запустить процесс с strace

strace node --max-old-space-size=128000 my_memory_consuming_process.js

Я недавно столкнулся с этой же проблемой и столкнулся с этой темой, но моя проблема была с React Приложение. Ниже изменения в команде запуска узла решили мои проблемы.

Синтаксис

node --max-old-space-size=<size> path-to/fileName.js

пример

node --max-old-space-size=16000 scripts/build.js

Почему размер 16000 в макс. Старомодном размере?

Как правило, это зависит от того, какая память выделена для этого потока, а также от настроек вашего узла.

Как проверить и дать правильный размер?

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

const v8 = require('v8');
const totalHeapSize = v8.getHeapStatistics().total_available_size;
const totalHeapSizeGb = (totalHeapSize / 1024 / 1024 / 1024).toFixed(2);
console.log('totalHeapSizeGb: ', totalHeapSizeGb);

Шаги, чтобы исправить -

  1. Откройте командную строку и введите %appdata% нажмите Ввод
  2. Перейдите к %appdata% > папка npm
  3. Открыть или изменить ng.cmd в вашем любимом редакторе
  4. добавлять --max_old_space_size=8192 в блок IF и ELSE

Ваш node.cmd после изменения файл выглядит так:

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe" "--max_old_space_size=8192" "%~dp0\node_modules\@angular\cli\bin\ng" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node "--max_old_space_size=8192" "%~dp0\node_modules\@angular\cli\bin\ng" %*
)

Я попробовал приведенный ниже код, и он работает нормально✌.

  • открыть терминал из корневого каталога проекта
  • выполнить cmd, чтобы установить новый размер.

    set NODE_OPTIONS = - max_old_space_size=8172

Или вы можете проверить ссылку для получения дополнительной информации https://github.com/nodejs/node/issues/10137

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

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

  1. Как все предлагали, увеличьте лимит памяти в узле, добавив эту команду:

            {
       "scripts":{
          "server":"node --max-old-space-size={size-value} server/index.js"
       }
    }
    

Здесь я определил для своего приложения 1536 (поскольку моя память модуля kubernetes была ограничена 2 ГБ, запрос 1,5 ГБ)

Так что всегда определяйте size-value на основе лимита инфраструктуры / архитектуры вашего внешнего интерфейса (немного меньше лимита)

Одно строгое обозначение здесь, в приведенной выше команде, используйте --max-old-space-size после node команда не после имени файла server/index.js.

  1. Если у тебя есть ngnix config, затем проверьте следующее:

    • worker_connections: 16384 (для тяжелых клиентских приложений)[nginx по умолчанию 512 подключений на worker, что слишком мало для современных приложений]

    • использовать: epoll (эффективный метод)[nginx поддерживает различные методы обработки соединения]

    • http: добавьте следующие вещи, чтобы освободить вашего рабочего от выполнения каких-либо нежелательных задач. ( client_body_timeout, reset_timeout_connection, client_header_timeout, keepalive_timeout, send_timeout ).

  2. Удалите все инструменты ведения журнала / отслеживания, такие как APM , Kafka , UTM tracking, Prerender(SEO) и т. Д. Промежуточного программного обеспечения или выключите.

  3. Теперь отладка на уровне кода : в вашем основном server файл, удалите ненужные console.log который просто печатает сообщение.

  4. Теперь проверьте каждый маршрут сервера, т.е. app.get() , app.post() ... ниже сценарии:

  • data => if(data) res.send(data)// вам действительно нужно ждать данных или этот api возвращает что-то в ответ, чего я должен ждать ?? , Если нет, то измените следующим образом:
      data => res.send(data) // this will not block your thread, apply everywhere where it's needed
  • другая часть: если ошибки нет, просто return res.send({}), НЕТ console.log here.

  • часть ошибки: некоторые люди определяют как error или же errчто создает путаницу и ошибки. как это:

            `error => { next(err) } // here err is undefined`
    
     `err => {next(error) } // here error is undefined`
    
     `app.get(API , (re,res) =>{
         error => next(error) // here next is not defined
      })`
    
  • Удалить winston , elastic-epm-node другие неиспользуемые библиотеки, использующие npx depcheck команда.

  • В служебном файле axios проверьте методы и ведение журнала правильно или нет:

              if(successCB) console.log("success") successCB(response.data) // here it's wrong statement, because on success you are just logging and then `successCB` sending  outside the if block which return in failure case also.
    
  • Спасайтесь от использования stringify , parseи т.д. на доступном большом наборе данных. (что я также вижу в ваших журналах, показанных выше.

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

Упомяну 2 типа решения.

Мое решение: в моем случае я добавляю это в свои переменные среды:

      export NODE_OPTIONS=--max_old_space_size=20480

Но даже если я перезапущу свой компьютер, он все равно не работает. Папка моего проекта находится в d: \ disk. Поэтому я удаляю свой проект на c:\ disk, и он сработал.

Решение моего товарища по команде: конфигурация package.json также работает.

      "start": "rimraf ./build && react-scripts --expose-gc --max_old_space_size=4096 start",

Для других новичков, таких как я, которые не нашли подходящего решения для этой ошибки, проверьте установленную версию узла (x32, x64, x86). У меня 64-битный процессор, и я установил версию узла x86, что вызвало CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory ошибка.

Юникс (Mac OS)

  1. Откройте терминал и откройте наш файл .zshrc , используя nano , например так (это создаст его, если он не существует):

    nano ~/.zshrc

  2. Обновите нашу переменную среды NODE_OPTIONS , добавив следующую строку в наш открытый в данный момент файл .zshrc :

    export NODE_OPTIONS=--max-old-space-size=8192 # increase node memory limit

Обратите внимание, что мы можем установить любое количество передаваемых мегабайт, при условии, что в нашей системе достаточно памяти (здесь мы передаем 8192 мегабайта, что составляет примерно 8 ГБ) .

  1. Сохраните и выйдите из nano, нажав: ctrl + x, тогда yдоговориться и наконец enterчтобы сохранить изменения.

  2. Закройте и снова откройте терминал , чтобы убедиться, что наши изменения были распознаны.

  3. Мы можем распечатать содержимое нашего файла .zshrc , чтобы увидеть, были ли сохранены наши изменения следующим образом: cat ~/.zshrc.

Линукс (Убунту)

  1. Откройте терминал и откройте файл .bashrc с помощью nano следующим образом:

    nano ~/.bashrc

Остальные шаги аналогичны шагам Mac выше, за исключением того, что мы, скорее всего, будем использовать ~/.bashrcпо умолчанию ( в отличие от ~/.zshrc) . Таким образом, эти значения должны быть заменены!

Ссылка на документы Nodejs

Я пробовал это NODE_OPTIONS= --max-old-space-size=8192 .

работает нормально для меня.

одно предложение:

только что попытался прокомментировать console.log() на терминале. потому что это также займет память. и использовать

Если вы хотите глобально изменить память для узла (Windows), перейдите в расширенные настройки системы -> переменные среды -> новая пользовательская переменная

variable name = NODE_OPTIONS
variable value = --max-old-space-size=4096

Вы также можете изменить переменные среды Window с помощью:

 $env:NODE_OPTIONS="--max-old-space-size=8192"

Воспользуйтесь опцией --optimize-for-size. Он будет сосредоточен на использовании меньшего количества таранов.

В моем случае я обновил версию node.js до последней (версия 12.8.0), и она работала как шарм.

У меня была эта ошибка на AWS Elastic Beanstalk, обновление типа экземпляра с t3.micro (бесплатный уровень) до t3.small исправило ошибку.

Обновите узел до последней версии. Я был на узле 6.6 с этой ошибкой и обновился до 8.9.4, и проблема ушла.

Эта команда работает отлично. У меня в ноутбуке 8 ГБ оперативной памяти, поэтому я установил размер =8192. Это все о оперативной памяти, а также вам необходимо указать имя файла. Я запускаю команду npm run build, поэтому использовал build.js.

node --expose-gc --max-old-space-size=8192 node_modules/react-scripts/scripts/build.js

Для Angular, вот как я исправил

В Package.json, внутри script тег добавить это

      "scripts": {
  "build-prod": "node --max_old_space_size=5048 ./node_modules/@angular/cli/bin/ng build --prod",
},

Сейчас в terminal/cmd Вместо того, чтобы использовать ng build --prod просто используйте

      npm run build-prod

Если вы хотите использовать эту конфигурацию для build только просто удалить --prod из всех 3 мест

Если какой-либо из приведенных ответов не работает для вас, проверьте установленный узел, совместим ли он (например, 32-битный или 64-битный) с вашей системой. Обычно этот тип ошибки возникает из-за несовместимости версий узла и ОС, и терминал / система не сообщит вам об этом, но будет держать вас в состоянии нехватки памяти.

Просто увеличьте кучную память с 1 до 8 ГБ для windows open powershell или cmd в каталоге вашего проекта и введите команду ниже, для mac open терминал в этом каталоге

node --max-old-space-size={size in MBs} index.js

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

Если вы пытаетесь запустить не node сам, но какой-то другой софт, например webpack Вы можете использовать переменную среды и cross-env пакет:

$ cross-env NODE_OPTIONS='--max-old-space-size=4096' \
  webpack --progress --config build/webpack.config.dev.js
Другие вопросы по тегам