Como determino o “tamanho do espaço antigo máximo” correto para node.js?

100

Estou tendo problemas para entender como o Node.js age com base no parâmetro max-old-space-size.

No meu caso, por exemplo, estou executando duas t2.smallinstâncias da AWS (2 GB de RAM).

Não sei por que, mas configurei max-old-space-size=4096(4 GB). O que o nó faz neste caso? Essa configuração pode levar a uma possível falha de alocação de memória?

Como determino o valor correto de com max-old-space-sizebase nos recursos do servidor?

Meu aplicativo está constantemente aumentando o uso de memória e estou tentando entender tudo sobre o interior do nó.

Borjante
fonte
8
Estou adicionando um comentário agora que vejo que isso está deixando muito quiete de visão. Levei uma semana inteira para perceber que meu aplicativo NodeJS não tinha vazamento de memória, mas que o coletor de lixo nunca entrou em ação. Esteja ciente disso em sistemas com pouca memória, como instâncias t2.micro ou t2.small. O servidor vai travar por causa da RAM não disponível.
Borjante
Havia uma maneira de fazer o coletor de lixo entrar em ação?
ZG101
@Borjante por que o coletor de lixo não estava funcionando?
divino
2
O max-old-space-size configurado tinha um limite maior do que a quantidade total de RAM que a máquina tinha.
Borjante
Vale --optimize-for-sizea pena tentar reduzir o uso de memória.
Constantinos

Respostas:

135

"Espaço antigo" é a maior e mais configurável seção do heap gerenciado do V8 (também conhecido como coleta de lixo) (ou seja, onde os objetos JavaScript residem), e o --max-old-space-sizesinalizador controla seu tamanho máximo. Conforme o consumo de memória se aproxima do limite, o V8 gastará mais tempo na coleta de lixo em um esforço para liberar memória não utilizada.

Se o consumo de memória heap (ou seja, objetos ativos que o GC não pode liberar) exceder o limite, o V8 travará seu processo (por falta de alternativa), portanto, você não deseja defini-lo muito baixo. Claro, se você definir um valor muito alto, o uso de heap adicional que o V8 permitirá pode fazer com que seu sistema geral fique sem memória (e troque ou elimine processos aleatórios, por falta de alternativa).

Em resumo, em uma máquina com 2 GB de memória, eu provavelmente configuraria --max-old-space-sizepara cerca de 1,5 GB para deixar alguma memória para outros usos e evitar a troca.

jmrk
fonte
6
Isso é exatamente o que eu esperava obter como resposta, descrevendo o caso extremo em que o sistema ou o Node ficam sem memória.
Borjante
2
@jmrk: Parece que você está totalmente certo, mas quando estou usando 2 GB de RAM e 4 GB de swap e definindo "--max-old-space-size" para 4 GB, o processo de nó consome toda a memória RAM e fica preso em 1,9 GB. A questão é "Por que trocar é evitar usar ??" (Node versão 8.11.1)
Manish Trivedi
1
O sinalizador deve substituir qualquer outra coisa. Verifique novamente se há erros de digitação.
jmrk
2
De d8 --help:--max-old-space-size (max size of the old space (in Mbytes))
jmrk
21

Atualização de 2020

Essas opções agora são documentadas oficialmente por nó . Para uma máquina de 2 GB, você provavelmente deve usar:

NODE_OPTIONS=--max-old-space-size=1536

Para determinar a quantidade a ser usada : Você pode ver a memória disponível em uma máquina Linux usando free -m. Observe que você pode usar o freee a buffers/cachememória combinados, pois buffers/cachepodem ser jogados fora (esses buffers e cache são uma boa maneira de usar a memória não utilizada de outra forma).

Observe a documentação oficial paramax-old-space-size também menções:

Em uma máquina com 2 GB de memória, considere definir isso para 1536 (1,5 GB)

Daí o valor acima. Considere que a quantidade de memória necessária para o sistema operacional básico não muda muito, então você poderia felizmente fazer 3,5 em uma máquina de 4 GB, etc.

mikemaccana
fonte
2
No link que você compartilhou nos documentos do Node.js, está escrito: "Em uma máquina com 2 GB de memória, considere definir isso para 1536 (1,5 GB)"
Idan Dagan
1
Obrigado @IdanDagan, vou acrescentar isso à resposta.
mikemaccana,
11

Este erro ocorre quando a memória alocada para o aplicativo em execução é menor que a memória necessária. Por padrão, o limite de memória em Node.js é 512 MB. Para aumentar essa quantidade, você precisa definir o argumento de limite de memória —-max-old-space-size. Isso ajudará a evitar um problema de limite de memória.

node --max-old-space-size=1024 index.js #increase to 1gb
node --max-old-space-size=2048 index.js #increase to 2gb
node --max-old-space-size=3072 index.js #increase to 3gb
node --max-old-space-size=4096 index.js #increase to 4gb
node --max-old-space-size=5120 index.js #increase to 5gb
node --max-old-space-size=6144 index.js #increase to 6gb
node --max-old-space-size=7168 index.js #increase to 7gb
node --max-old-space-size=8192 index.js #increase to 8gb

https://medium.com/@vuongtran/how-to-solve-process-out-of-memory-in-node-js-5f0de8f8464c

S. V
fonte
e deve ser mais do que a memória Ram alocada
HD ..
Não tenho mais certeza de que isso seja verdade. Certamente em um sistema eu tenho acesso ao nó em execução 10.20.1, posso ver (com node --v8-options) que o padrão relatado é 4096 e sem definir max-old-space-sizeo conjunto de testes que estou executando obtém até 1,5 Gb alocado sem problemas. O artigo médio com link é de 2016, então é provável que as coisas tenham mudado desde que foi escrito.
JaySeeAre
1
É difícil encontrar corroboração nisso; Não consigo encontrar nada explícito nos documentos para V8 ou Node. Outro sistema que tenho relata o padrão para v10, 12 e 14. como 0. FWIW Eu encontrei alguns blogueiros mais recentes declarando memória máxima como 1,5 Gb ( tejom.github.io/general/nodejs/v8/debugging/2017/ 01/16 /… ) e que v12 tem um máximo dinâmico baseado no sistema ( idginsiderpro.com/article/3257673/… ).
JaySeeAre
4
node -e "console.log(`node heap limit = ${require('v8').getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)"-> v12.18.0 e v14.3.0 -> 2096Mb, v10.20.1 -> 1432Mb
JaySeeAre
2
@JaySeeAre, obrigado por esse comando para mostrar o heap_size_limit. Para um shell UNIX normal, ele precisa ser citado de forma diferente:node -e 'console.log(`node heap limit = ${require("v8").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'
Sam Watkins
-9

Se você deseja apenas que funcione a partir do projeto em que está trabalhando, siga as duas etapas:

  1. Em seu projeto cd para node_module / @ angular cd node_module / @ angular

  2. Agora execute o comando abaixo export NODE_OPTIONS = - max-old-space-size = 8192

satish suryawanshi
fonte
18
Por que precisaria ir para o diretório @angular para definir uma var de ambiente?
mgamsjager