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
Я столкнулся с этой проблемой при попытке отладки с помощью 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);
Шаги, чтобы исправить -
- Откройте командную строку и введите
%appdata%
нажмите Ввод - Перейдите к
%appdata%
> папка npm - Открыть или изменить
ng.cmd
в вашем любимом редакторе - добавлять
--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
Недавно в одном из моих проектов возникла такая же проблема. Пробовал пару вещей, которые каждый может попробовать в качестве отладки, чтобы определить основную причину:
Как все предлагали, увеличьте лимит памяти в узле, добавив эту команду:
{ "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
.
Если у тебя есть
ngnix
config, затем проверьте следующее:worker_connections:
16384
(для тяжелых клиентских приложений)[nginx по умолчанию512
подключений наworker
, что слишком мало для современных приложений]использовать:
epoll
(эффективный метод)[nginx поддерживает различные методы обработки соединения]http: добавьте следующие вещи, чтобы освободить вашего рабочего от выполнения каких-либо нежелательных задач. ( client_body_timeout, reset_timeout_connection, client_header_timeout, keepalive_timeout, send_timeout ).
Удалите все инструменты ведения журнала / отслеживания, такие как
APM , Kafka , UTM tracking, Prerender
(SEO) и т. Д. Промежуточного программного обеспечения или выключите.Теперь отладка на уровне кода : в вашем основном
server
файл, удалите ненужныеconsole.log
который просто печатает сообщение.Теперь проверьте каждый маршрут сервера, т.е.
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
и т.д. на доступном большом наборе данных. (что я также вижу в ваших журналах, показанных выше.
- И последнее, но не менее важное: каждый раз, когда ваше приложение аварийно завершает работу или перезапускаются модули, проверяйте журналы. В журнале специально ищите этот раздел:
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)
Откройте терминал и откройте наш файл .zshrc , используя nano , например так (это создаст его, если он не существует):
nano ~/.zshrc
Обновите нашу переменную среды NODE_OPTIONS , добавив следующую строку в наш открытый в данный момент файл .zshrc :
export NODE_OPTIONS=--max-old-space-size=8192 # increase node memory limit
Обратите внимание, что мы можем установить любое количество передаваемых мегабайт, при условии, что в нашей системе достаточно памяти (здесь мы передаем 8192 мегабайта, что составляет примерно 8 ГБ) .
Сохраните и выйдите из nano, нажав:
ctrl + x
, тогдаy
договориться и наконецenter
чтобы сохранить изменения.Закройте и снова откройте терминал , чтобы убедиться, что наши изменения были распознаны.
Мы можем распечатать содержимое нашего файла .zshrc , чтобы увидеть, были ли сохранены наши изменения следующим образом:
cat ~/.zshrc
.
Линукс (Убунту)
Откройте терминал и откройте файл .bashrc с помощью nano следующим образом:
nano ~/.bashrc
Остальные шаги аналогичны шагам Mac выше, за исключением того, что мы, скорее всего, будем использовать
~/.bashrc
по умолчанию ( в отличие от ~/.zshrc) . Таким образом, эти значения должны быть заменены!
Я пробовал это 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