O Node.js fica sem memória


245

Hoje eu executei meu script para indexação do sistema de arquivos para atualizar o índice de arquivos RAID e após 4h ele travou com o seguinte erro:

[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

O servidor está equipado com 16 GB de RAM e 24 GB de SSD. Eu duvido que meu script tenha excedido 36 gb de memória. Pelo menos não deveria

O script cria um índice de arquivos armazenados como Array of Objects com metadados de arquivos (datas de modificação, permissões, etc., sem big data)

Aqui está o código de script completo: http://pastebin.com/mjaD76c3

Eu já experimentei problemas estranhos de nós no passado com este script, o que me forçou, por exemplo. divida o índice em vários arquivos, pois o nó estava com falha ao trabalhar em arquivos grandes como o String. Existe alguma maneira de melhorar o gerenciamento de memória do nodejs com enormes conjuntos de dados?

Respostas:


314

Se bem me lembro, existe um limite padrão estrito para o uso de memória na V8 de cerca de 1,7 GB, se você não aumentar manualmente.

Em um de nossos produtos, seguimos esta solução em nosso script de implantação:

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

Também haveria um novo comando de espaço, mas como eu li aqui: um tour pela coleta de lixo v8, o novo espaço coleta apenas os dados de curto prazo recém-criados e o espaço antigo contém todas as estruturas de dados referenciadas que devem estar em seu caso, a melhor opção.


Da mesma forma esta configuração é para nodejs independente sobre o quadro @ Simer.
Felix

Estou desenvolvendo com o angular 4 e obtendo o mesmo problema. Qual deve ser o arquivo yourFile.js para o aplicativo angular?
Vikram

@VikramSingh você está usando ng serveou distribui o resultado da ng buildpasta / dist por outro servidor, como o express? Mas se o seu projeto Angular estiver usando mais do que a memória padrão de 1,7 GB, talvez você tenha um problema de arquitetura em seu aplicativo? Parece que você está usando o env desenvolvimento com NMP começar talvez esta seja uma solução para ele github.com/mgechev/angular-seed/issues/2063
Felix

Eu estou usando construção ng com cli angular e AOT (pasta dist)
Vikram

2
índice, js arquivo @Techdive que você usa para iniciar o servidor
Basit

77

Apenas no caso de alguém encontrar isso em um ambiente em que não pode definir diretamente as propriedades do nó (no meu caso, uma ferramenta de construção):

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

Você pode definir as opções do nó usando uma variável de ambiente se não puder transmiti-las na linha de comandos.


Você pode explicar o que quer dizer quando diz "... definir as opções do nó usando uma variável de ambiente .."?
Keselme 24/01/19

6
@Keselme Uma variável de ambiente é uma variável que foi definida no servidor a partir da qual todos os processos podem ler os dados. Abra um terminal SSH no seu servidor e digite: MY_VAR = hello e digite: echo $ MY_VAR. Você verá que ele imprime "olá" no terminal. Você acabou de definir uma variável de ambiente e lê-la novamente.
Rob Evans

trabalhou no Ubuntu 18.04, acabou de adicionar o comando de exportação para o meu arquivo bashrc
Rahal Kanishka

76

Se você deseja aumentar o uso de memória do nó globalmente - não apenas um script único, é possível exportar a variável de ambiente, assim:
export NODE_OPTIONS=--max_old_space_size=4096

Então você não precisa jogar com arquivos ao executar builds como npm run build.


1
Como uma conveniência adicional, adicione ao perfil bash_profile ou zsh.
Tropicalrambler

24

Eu encontrei esse problema ao tentar depurar com o VSCode, então só queria adicionar isso é como você pode adicionar o argumento à sua configuração de depuração.

Você pode adicioná-lo à runtimeArgspropriedade da sua configuração em launch.json.

Veja o exemplo abaixo.

{
"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"
        ]
    }
]}

21

Aqui estão alguns valores de sinalizador para adicionar algumas informações adicionais sobre como permitir mais memória quando você inicia o servidor do nó.

1GB - 8GB

#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 

pode-se continuar aumentando em potências de 2? deve-se configurá-lo maior que a memória do sistema? caso contrário, o que é uma boa proporção de memória do sistema e tamanho máximo de espaço antigo?
Harry Moreno

3
@HarryMoreno Você pode realmente colocar qualquer valor numérico que desejar. Não precisa estar no poder de 2. No entanto, não tenho certeza da proporção. É apenas um limite máximo, não estará usando toda a memória. Eu defini-lo-ia tão alto quanto você precisa e, em seguida, reduzi-lo, se necessário.
Nicholas Porter

Vou dar uma ram de sistema - 1gb uma tentativa. Supondo que essa vm seja apenas para executar este aplicativo de nó.
Harry Moreno

2
@HarryMoreno Uma boa taxa de memória do sistema para o tamanho máximo de espaço antigo depende inteiramente do que mais está sendo executado em sua máquina. Você pode aumentá-lo em potências de dois - ou pode usar qualquer número. Você pode configurá-lo maior que a memória do sistema - mas encontrará problemas de troca.
Gigimoi 29/07/19

20

eu estava lutando com isso mesmo depois de definir --max-old-space-size.

Então percebi a necessidade de colocar opções --max-old-space-size antes do script de karma.

Também é melhor especificar as duas sintaxes --max-old-space-size e --max_old_space_size meu script para karma:

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

referência https://github.com/angular/angular-cli/issues/1652


5
" melhor especificar ambas as sintaxes --max-old-space-size e --max_old_space_size " - você não precisa fazer isso, elas são sinônimos. Em nodejs.org/api/cli.html#cli_options : "Todas as opções, incluindo as opções V8, permitem que as palavras sejam separadas por traços (-) ou sublinhados (_)."
ZachB

6
O tamanho máximo de executável foi removido e termina com um erro quando é usado: github.com/nodejs/node/issues/13341
crashbus

Eu tive que cortar --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizee deu
certo



10

Etapas para corrigir esse problema (no Windows) -

  1. Abra o prompt de comando e digite %appdata% press enter
  2. Navegar para %appdata% > pasta npm
  3. Abrir ou Editar ng.cmd no seu editor favorito
  4. Adicione --max_old_space_size=8192ao bloco IF e ELSE

Seu node.cmdarquivo fica assim após a alteração:

@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" %*
)

Isso é específico do Windows. O OP não mencionou nada sobre o Windows.
Dan Dascalescu

@DanDascalescu Resposta atualizada. Obrigado por notificar
Umang Patwa

6

A seguinte variável de ambiente pode ser usada:

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

Outra nota: console.log() também consome memória no terminal.

apenas tentei comentar o console.log () no terminal. porque isso também vai levar memória.


6
Isso é uma resposta ou comentário para alguma resposta? Há muitas respostas comNODE_OPTIONS= --max-old-space-size=somesize
barbsan

5

se você deseja alterar a memória globalmente para o nó (windows), vá para configurações avançadas do sistema -> variáveis ​​de ambiente -> nova variável do usuário

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


4

Eu só quero acrescentar que em alguns sistemas, mesmo aumentando o limite de memória do nó --max-old-space-size, não é suficiente e há um erro do sistema operacional como este:

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

Nesse caso, provavelmente é porque você atingiu o mmap máximo por processo.

Você pode verificar o max_map_count executando

sysctl vm.max_map_count

e aumentá-lo executando

sysctl -w vm.max_map_count=655300

e corrija-o para não ser redefinido após uma reinicialização adicionando esta linha

vm.max_map_count=655300

no /etc/sysctl.conf arquivo

Confira aqui para mais informações.

Um bom método para analisar o erro é executar o processo com strace

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

3

Eu enfrentei esse mesmo problema recentemente e me deparei com esse segmento, mas meu problema era com o ReactApp. Abaixo, as alterações no comando start do nó resolveram meus problemas.

Sintaxe

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

Exemplo

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

Por que o tamanho é 16000 no tamanho máximo de espaço antigo?

Basicamente, isso varia depende da memória alocada para esse encadeamento e das configurações do nó.

Como verificar e dar o tamanho certo?

Isso é basicamente ficar no nosso motor v8. o código abaixo ajuda a entender o tamanho da pilha do mecanismo do nó local v8.

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

2

Acabei de enfrentar o mesmo problema com minha instância EC2 t2.micro, que possui 1 GB de memória.

Resolvi o problema criando um arquivo de troca usando esse URL e defini a seguinte variável de ambiente.

export NODE_OPTIONS=--max_old_space_size=4096

Finalmente, o problema se foi.

Espero que seja útil para o futuro.


1

Para o caso de ajudar as pessoas com esse problema ao usar aplicativos nodejs que produzem logs pesados, um colega resolveu esse problema direcionando as saídas padrão para um arquivo.


1

Se você está tentando iniciar não nodeele próprio, mas algum outro software, por exemplo, webpackvocê pode usar a variável de ambiente e o cross-envpacote:

$ cross-env NODE_OPTIONS='--max-old-space-size=4096' \
  webpack --progress --config build/webpack.config.dev.js

1

Para empacotamento angular de projeto, adicionei a linha abaixo ao meu arquivo pakage.json na seção scripts .

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

Agora, para agrupar meu código, eu uso em npm run build-prodvez deng build --requiredFlagsHere

espero que isto ajude!


0

Atualize o nó para a versão mais recente. Eu estava no nó 6.6 com esse erro e atualizei para 8.9.4 e o problema desapareceu.


0

No meu caso, eu corri npm installna versão anterior do nó, depois de um dia atualizei a versão do nó e ram npm installpara alguns módulos. Depois disso, eu estava recebendo esse erro. Para corrigir esse problema, excluí a pasta node_module de cada projeto e executei npm installnovamente.

Espero que isso possa resolver o problema.

Nota: Isso estava acontecendo na minha máquina local e foi corrigido apenas na máquina local.


0

Este comando funciona perfeitamente. Como tenho 8 GB de RAM no meu laptop, defino o tamanho = 8192. É tudo sobre ram e você também precisa definir o nome do arquivo. Eu executo o comando npm run build , por isso usei o build.js .

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

0

No meu caso, atualizei a versão do node.js. para a mais recente e funcionou como um encanto.


Olá Angela e bem-vindo ao SO! Talvez você possa especificar a versão exata do Node.js atualizada para futuros leitores? Obrigado!
kant312 12/06

Atualizei para a versão mais recente do LTS: 12.18.0
Angela Rana
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.