Node.js accumula memoria insufficiente


247

Oggi ho eseguito il mio script per l'indicizzazione del filesystem per aggiornare l'indice dei file RAID e dopo 4 ore si è bloccato con il seguente errore:

[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

Il server è dotato di RAM da 16 GB e scambio SSD da 24 GB. Dubito fortemente che la mia sceneggiatura abbia superato i 36 GB di memoria. Almeno non dovrebbe

Lo script crea l'indice dei file archiviati come array di oggetti con metadati dei file (date di modifica, autorizzazioni, ecc., Nessun big data)

Ecco il codice completo dello script: http://pastebin.com/mjaD76c3

Ho già sperimentato strani problemi di nodo in passato con questo script che mi ha costretto ad es. dividere l'indice in più file mentre il nodo era glitch quando si lavorava su file di grandi dimensioni come String. Esiste un modo per migliorare la gestione della memoria di nodejs con enormi set di dati?

Risposte:


315

Se ricordo bene, esiste un limite standard rigoroso per l'utilizzo della memoria in V8 di circa 1,7 GB, se non lo si aumenta manualmente.

In uno dei nostri prodotti abbiamo seguito questa soluzione nel nostro script di distribuzione:

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

Ci sarebbe anche un nuovo comando di spazio, ma mentre leggo qui: a-tour-of-v8-garbage-collection il nuovo spazio raccoglie solo i dati a breve termine appena creati e il vecchio spazio contiene tutte le strutture di dati di riferimento che dovrebbero essere in nel tuo caso l'opzione migliore.


Allo stesso modo questa configurazione è per nodejs indipendentemente dal framework. @ Simer
Felix

Sto sviluppando con Angular 4 e ricevendo lo stesso problema, quale dovrebbe essere il tuo file File.js per l'app angolare?
Vikram,

@VikramSingh stai usando ng serveo distribuisci il risultato della ng buildcartella / dist da un altro server web come express? Ma se il tuo progetto Angular utilizza più della memoria standard da 1,7 GB di quella che potresti avere un problema architettonico nella tua applicazione? Sembra che tu stia usando lo sviluppo env con nmp start forse questa è una soluzione per questo github.com/mgechev/angular-seed/issues/2063
Felix,

Sto usando ng build con cli e aot angolari (cartella dist)
Vikram,

2
index, file js @Techdive che usi per avviare il server
Basit

77

Nel caso in cui qualcuno si imbatta in questo in un ambiente in cui non è possibile impostare direttamente le proprietà del nodo (nel mio caso uno strumento di compilazione):

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

È possibile impostare le opzioni del nodo utilizzando una variabile di ambiente se non è possibile passarle sulla riga di comando.


Puoi spiegare cosa intendi quando dici "... imposta le opzioni del nodo usando una variabile d'ambiente ..."?
Keselme,

6
@Keselme Una variabile di ambiente è una variabile impostata sul server da cui tutti i processi possono leggere i dati. Apri un terminale SSH sul tuo server e digita: MY_VAR = ciao quindi digita: echo $ MY_VAR. Vedrai che stampa "ciao" nel terminale. Hai appena impostato una variabile d'ambiente e riletta.
Rob Evans,

ha funzionato su Ubuntu 18.04, appena aggiunto il comando export al mio file bashrc
Rahal Kanishka,

76

Se si desidera aumentare l'utilizzo della memoria del nodo a livello globale, non solo un singolo script, è possibile esportare la variabile di ambiente, in questo modo:
export NODE_OPTIONS=--max_old_space_size=4096

Quindi non è necessario giocare con i file quando si eseguono build come npm run build.


1
Come ulteriore comodità, aggiungi al profilo bash_profile o zsh.
Tropicalrambler il

24

Ho riscontrato questo problema durante il tentativo di debug con VSCode, quindi volevo solo aggiungere questo è come è possibile aggiungere l'argomento alla configurazione del debug.

Puoi aggiungerlo alla runtimeArgsproprietà della tua configurazione in launch.json.

Vedi esempio sotto.

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

Ecco alcuni valori flag per aggiungere ulteriori informazioni su come consentire più memoria all'avvio del server del nodo.

1 GB - 8 GB

#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 

si può continuare ad aumentarlo con potenze di 2? si dovrebbe impostarlo più grande della memoria di sistema? in caso contrario, qual è una buona memoria di sistema rispetto al rapporto spazio-vecchio-dimensione massima?
Harry Moreno,

3
@HarryMoreno Puoi effettivamente inserire qualsiasi valore numerico che ti piace. Non deve essere al potere di 2. Non sono sicuro del rapporto però. È solo un limite massimo, non utilizzerà tutta la memoria. Lo impostarei solo su quanto necessario, quindi ridimensionarlo se necessario.
Nicholas Porter,

Darò una prova del sistema ram - 1 GB. Supponendo che questo vm sia solo per l'esecuzione di questa app nodo.
Harry Moreno,

2
@HarryMoreno Una buona memoria di sistema rispetto al rapporto spazio-vecchio-spazio massimo dipende interamente da cos'altro è in esecuzione sul tuo computer. Puoi aumentarlo con poteri di due o puoi usare qualsiasi numero. Puoi impostarlo più grande della memoria di sistema, ma colpirai problemi di scambio.
Gigimoi,

20

stavo lottando con questo anche dopo aver impostato - max-old-space-size.

Poi ho capito che dovevo mettere le opzioni - max-old-space-size prima della sceneggiatura del karma.

anche meglio specificare entrambe le sintassi --max-old-space-size e --max_old_space_size il mio script per il 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

riferimento https://github.com/angular/angular-cli/issues/1652


5
" meglio specificare entrambe le sintassi --max-old-space-size e --max_old_space_size " - non è necessario eseguire questa operazione, sono sinonimi. Da nodejs.org/api/cli.html#cli_options : "Tutte le opzioni, comprese le opzioni V8, consentono alle parole di essere separate da entrambi i trattini (-) o caratteri di sottolineatura (_)."
ZachB,

6
la dimensione max-eseguibile è stata rimossa e termina con un errore quando viene utilizzata: github.com/nodejs/node/issues/13341
crashbus

Ho dovuto tagliarlo --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizee ha funzionato
Sergey Pleshakov il


11

prima di tutto, trovare e riparare un porco di memoria con qualcosa come memwatch potrebbe aiutare.


10

I passaggi per risolvere questo problema (in Windows) -

  1. Aprire il prompt dei comandi e digitare %appdata%premere Invio
  2. Passare alla %appdata%cartella> npm
  3. Apri o modifica ng.cmd nel tuo editor preferito
  4. Aggiungi --max_old_space_size=8192al blocco IF ed ELSE

Il tuo node.cmdfile appare così dopo la modifica:

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

Questo è specifico di Windows. L'OP non ha menzionato nulla di Windows.
Dan Dascalescu,

@DanDascalescu Risposta aggiornata. Grazie per
avermelo

6

È possibile utilizzare la seguente variabile di ambiente:

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

Un'altra nota: console.log()consuma anche memoria nel terminale.

ho appena provato a commentare console.log () sul terminale. perché anche questo richiederà memoria.


6
È una risposta o un commento a qualche risposta? Ci sono molte risposte conNODE_OPTIONS= --max-old-space-size=somesize
barbsan il

5

se vuoi cambiare la memoria a livello globale per il nodo (windows) vai alle impostazioni di sistema avanzate -> variabili di ambiente -> nuova variabile utente

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


4

Voglio solo aggiungere che in alcuni sistemi, anche aumentando il limite di memoria del nodo con --max-old-space-size, non è abbastanza e c'è un errore del sistema operativo come questo:

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

In questo caso, probabilmente è perché hai raggiunto il mmap massimo per processo.

Puoi controllare max_map_count eseguendo

sysctl vm.max_map_count

e aumentarlo correndo

sysctl -w vm.max_map_count=655300

e risolverlo per non ripristinarlo dopo un riavvio aggiungendo questa riga

vm.max_map_count=655300

nel /etc/sysctl.conffile.

Controlla qui per maggiori informazioni.

Un buon metodo per analizzare l'errore è eseguire il processo con strace

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

3

Di recente ho riscontrato lo stesso problema e mi sono imbattuto in questo thread, ma il mio problema era con l' Reactapp. Di seguito le modifiche nel comando di avvio del nodo hanno risolto i miei problemi.

Sintassi

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

Esempio

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

Perché la dimensione è 16000 nella dimensione spazio massimo-vecchio?

Fondamentalmente, varia in base alla memoria allocata a quel thread e alle impostazioni del nodo.

Come verificare e dare la giusta dimensione?

Questo è fondamentalmente rimanere nel nostro motore v8. sotto il codice ti aiuta a capire la dimensione dell'heap del tuo motore nodo v8 locale.

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

2

Ho appena affrontato lo stesso problema con la mia istanza EC2 t2.micro che ha 1 GB di memoria.

Ho risolto il problema creando il file di scambio utilizzando questo url e impostato la seguente variabile di ambiente.

export NODE_OPTIONS=--max_old_space_size=4096

Finalmente il problema è andato.

Spero che sarebbe utile per il futuro.


1

Nel caso in cui ciò possa aiutare le persone ad avere questo problema durante l'utilizzo delle app nodejs che producono registrazioni pesanti, un collega ha risolto il problema eseguendo il piping degli output standard su un file.


1

Se stai provando a lanciare non nodese stesso, ma qualche altro webpacksoftware , ad esempio puoi usare la variabile d'ambiente e il cross-envpacchetto:

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

1

Per il raggruppamento di progetti angolare, ho aggiunto la riga seguente al mio file pakage.json nella sezione script .

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

Ora, per raggruppare il mio codice, utilizzo npm run build-prodinvece ding build --requiredFlagsHere

spero che questo ti aiuti!


0

Aggiorna nodo all'ultima versione. Ero sul nodo 6.6 con questo errore e aggiornato a 8.9.4 e il problema è andato via.


0

Nel mio caso avevo eseguito la npm installversione precedente del nodo, dopo qualche giorno ho aggiornato la versione del nodo e la ram npm installper alcuni moduli. Dopo questo ho ricevuto questo errore. Per risolvere questo problema, ho eliminato la cartella node_module da ciascun progetto ed eseguitonpm install nuovo.

Spero che questo possa risolvere il problema.

Nota: questo stava accadendo sul mio computer locale e si è risolto solo sul computer locale.


0

Questo comando funziona perfettamente. Ho 8 GB di RAM nel mio laptop, quindi ho impostato la dimensione = 8192. Si tratta di ram e inoltre è necessario impostare il nome del file. Corro npm run comando build ecco perché ho usato build.js .

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

0

Nel mio caso, ho aggiornato la versione node.js alla più recente e ha funzionato come un fascino.


Ciao Angela e benvenuta in SO! Potresti forse specificare la versione esatta di Node.js che hai aggiornato per i lettori futuri? Grazie!
kant312,

Ho aggiornato all'ultima versione LTS: 12.18.0
Angela Rana, il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.