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

248

Сегодня я запустил свой скрипт для индексации файловой системы, чтобы обновить индекс файлов 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 с огромными наборами данных?

Lapsio
источник

Ответы:

316

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

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

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

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

Феликс
источник
Точно так же этот конфиг предназначен для nodejs независимо от фреймворка. @ Simer
Феликс
Я занимаюсь разработкой с angular 4 и получаю ту же проблему. Каким должен быть файл yourFile.js для приложения angular?
Викрам
@VikramSingh вы используете ng serveили распространяете результат ng buildпапки / dist другим веб-сервером, таким как express? Но если ваш проект Angular использует больше, чем стандартная память объемом 1,7 ГБ, у вас может возникнуть архитектурная проблема в вашем приложении? Похоже, что вы используете env разработки с nmp start, может быть, это решение для него github.com/mgechev/angular-seed/issues/2063
Феликс
Я использую ng build с угловым cli и aot (папка dist)
Викрам
2
индекс, JS файл @Techdive , который используется для запуска сервера
Basit
78

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

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

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

Камиэль Ванройдж
источник
Можете ли вы объяснить, что вы имеете в виду, когда говорите "... установить параметры узла с помощью переменной среды .."?
Кесельме
6
@Keselme Переменная среды - это переменная, установленная на сервере, с которой все процессы могут читать данные. Откройте терминал SSH на вашем сервере и введите: MY_VAR = hello, затем введите: echo $ MY_VAR. Вы увидите, что он печатает «привет» в терминале. Вы только что установили переменную окружения и прочитали ее обратно.
Роб Эванс
работал в Ubuntu 18.04, только что добавил команду экспорта в мой файл bashrc
Rahal
76

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

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

Максим Лузик
источник
1
Для дополнительного удобства добавьте в профиль bash_profile или zsh.
Tropicalrambler
24

Я столкнулся с этой проблемой при попытке отладки с помощью 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"
        ]
    }
]}
Astr-о
источник
22

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

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 
Николас Портер
источник
Можно ли продолжать увеличивать его в степени 2? следует ли устанавливать его больше, чем системная память? если нет, то каково хорошее соотношение системной памяти и максимального размера старого пространства?
Гарри Морено
3
@HarryMoreno Вы можете ввести любое числовое значение. Не обязательно быть во власти 2. Не уверен насчет соотношения, хотя. Это только максимальный предел, он не будет использовать всю память. Я просто установил бы это так высоко, как вам нужно, затем уменьшил бы, если это необходимо.
Николас Портер
Я дам системной памяти - 1 ГБ попробовать. Предполагая, что этот VM только для запуска этого приложения узла.
Гарри Морено
2
@HarryMoreno Хорошее соотношение системной памяти к максимальному старому размеру пространства полностью зависит от того, что еще работает на вашем компьютере. Вы можете увеличить его в степени двух или вы можете использовать любое число. Вы можете установить его больше, чем системная память - но вы столкнетесь с проблемами подкачки.
Gigimoi
20

я боролся с этим даже после установки --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

duchuy
источник
5
« Лучше всего указывать оба синтаксиса --max-old-space-size и --max_old_space_size » - вам не нужно это делать, это синонимы. Из nodejs.org/api/cli.html#cli_options : «Все опции, включая опции V8, позволяют разделять слова как тире (-), так и подчеркивания (_)».
ЗакБ
6
Максимальный размер исполняемого файла был удален и заканчивается при его использовании: github.com/nodejs/node/issues/13341
crashbus
Я должен был сократить это до, --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizeи это работало
Сергей Плешаков
16

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

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

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

Чандру
источник
1
Приветствия работали для меня, это может быть необходимоsudo npm -g install increase-memory-limit --unsafe-perm
Лев
11

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

NathanQ
источник
10

Действия по устранению этой проблемы (в Windows) -

  1. Откройте командную строку и введите %appdata%нажмите Enter
  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" %*
)
Уманг Патва
источник
Это специфично для Windows. ОП ничего не говорил о Windows.
Дан Даскалеску
@DanDascalescu Обновленный ответ. Спасибо за уведомление
Уманг Патва
6

Можно использовать следующую переменную среды:

NODE_OPTIONS= --max-old-space-size=8192 .

Еще одна заметка: console.log() также потребляет память в терминале.

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

Амар Повар
источник
6
Это ответ или комментарий к какому-либо ответу? Есть много ответов сNODE_OPTIONS= --max-old-space-size=somesize
Барбсан
5

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

variable name = NODE_OPTIONS
variable value = --max-old-space-size=4096
Ахмед Абуд
источник
4

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

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

    set NODE_OPTIONS=--max_old_space_size=8172

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

rkumar1904
источник
4

Я просто хочу добавить, что в некоторых системах, даже увеличивая ограничение памяти узла --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
jbaylina
источник
3

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

Синтаксис

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);
Venkat.R
источник
2

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

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

export NODE_OPTIONS=--max_old_space_size=4096

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

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

Бат-Орших Баавгайхуу
источник
1

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

Адриен Джоли
источник
1

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

$ cross-env NODE_OPTIONS='--max-old-space-size=4096' \
  webpack --progress --config build/webpack.config.dev.js
Piterden
источник
1

Для связывания угловых проектов я добавил следующую строку в мой файл pakage.json в разделе скриптов .

"build-prod": "node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --prod --base-href /"

Теперь, чтобы связать мой код, я использую npm run build-prodвместоng build --requiredFlagsHere

надеюсь это поможет!

rgantla
источник
0

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

Ричард Фрэнк
источник
0

В моем случае я работал npm installна предыдущей версии узла, через некоторое время я обновил версию узла и оперативную память npm installдля нескольких модулей. После этого я получил эту ошибку. Чтобы решить эту проблему, я удалил папку node_module из каждого проекта и запустилnpm install снова .

Надеюсь, что это может решить проблему.

Примечание: это происходило на моей локальной машине, и это было исправлено только на локальной машине.

Gampesh
источник
0

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

node --expose-gc --max-old-space-size=8192 node_modules/react-scripts/scripts/build.js
Таха Фаруки
источник
0

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

Анжела Рана
источник
Привет Анжела и добро пожаловать на ТАК! Не могли бы вы указать точную версию Node.js, которую вы обновили для будущих читателей? Спасибо!
kant312
Я обновился до последней версии LTS: 12.18.0
Анжела Рана