Node.js Heap nicht genügend Speicher


245

Heute habe ich mein Skript für die Dateisystemindizierung ausgeführt, um den RAID-Dateiindex zu aktualisieren, und nach 4 Stunden stürzte es mit folgendem Fehler ab:

[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

Der Server ist mit 16 GB RAM und 24 GB SSD-Swap ausgestattet. Ich bezweifle sehr, dass mein Skript mehr als 36 GB Speicherplatz hat. Zumindest sollte es nicht

Das Skript erstellt einen Index von Dateien, die als Array von Objekten mit Dateimetadaten gespeichert sind (Änderungsdaten, Berechtigungen usw., keine großen Datenmengen).

Hier ist der vollständige Skriptcode: http://pastebin.com/mjaD76c3

Ich habe in der Vergangenheit bereits seltsame Knotenprobleme mit diesem Skript erlebt, was mich z. Teilen Sie den Index in mehrere Dateien auf, da der Knoten bei der Arbeit an so großen Dateien wie String fehlerhaft war. Gibt es eine Möglichkeit, die Speicherverwaltung von nodejs mit riesigen Datenmengen zu verbessern?

Antworten:


313

Wenn ich mich richtig erinnere, gibt es in V8 ein striktes Standardlimit für die Speichernutzung von etwa 1,7 GB, wenn Sie es nicht manuell erhöhen.

In einem unserer Produkte haben wir diese Lösung in unserem Bereitstellungsskript befolgt:

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

Es würde auch einen neuen Space-Befehl geben, aber wie ich hier lese: a-tour-of-v8-garbage-collection Der neue Space sammelt nur die neu erstellten Kurzzeitdaten und der alte Space enthält alle referenzierten Datenstrukturen, die sich befinden sollten Ihr Fall die beste Option.


Auf die gleiche Weise ist diese Konfiguration für Nodejs unabhängig vom Framework. @ Simer
Felix

Ich entwickle mit Angular 4 und bekomme das gleiche Problem. Was sollte Ihre Datei.File.js für Angular App sein?
Vikram

@VikramSingh verwenden Sie ng serveoder verteilen Sie das Ergebnis des ng buildOrdners / dist von einem anderen Webserver wie Express? Wenn Ihr Angular-Projekt jedoch mehr als den Standardspeicher von 1,7 GB verwendet, haben Sie möglicherweise ein Architekturproblem in Ihrer Anwendung? Es sieht so aus, als ob Sie die Entwicklungsumgebung mit nmp start verwenden. Vielleicht ist dies eine Lösung dafür. Github.com/mgechev/angular-seed/issues/2063
Felix

Ich benutze ng build mit eckigen cli und aot (dist Ordner)
Vikram

2
Index, JS-Datei @Techdive, mit der Sie den Server starten
Basit

77

Nur für den Fall, dass jemand in einer Umgebung darauf stößt, in der er die Knoteneigenschaften nicht direkt festlegen kann (in meinem Fall ein Build-Tool):

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

Sie können die Knotenoptionen mithilfe einer Umgebungsvariablen festlegen, wenn Sie sie nicht in der Befehlszeile übergeben können.


Können Sie bitte erklären, was Sie meinen, wenn Sie sagen "... die Knotenoptionen mithilfe einer Umgebungsvariablen festlegen ..."?
Keselme

6
@Keselme Eine Umgebungsvariable ist eine Variable, die auf dem Server festgelegt wurde, von der alle Prozesse die Daten lesen können. Öffnen Sie ein SSH-Terminal für Ihren Server und geben Sie Folgendes ein: MY_VAR = Hallo. Geben Sie dann Folgendes ein: echo $ MY_VAR. Sie werden sehen, dass im Terminal "Hallo" gedruckt wird. Sie haben gerade eine Umgebungsvariable festgelegt und zurückgelesen.
Rob Evans

arbeitete an Ubuntu 18.04, fügte gerade den Exportbefehl zu meiner bashrc-Datei hinzu
Rahal Kanishka

76

Wenn Sie die Speichernutzung des Knotens global erhöhen möchten - nicht nur ein einzelnes Skript -, können Sie Umgebungsvariablen wie folgt exportieren:
export NODE_OPTIONS=--max_old_space_size=4096

Dann müssen Sie nicht mit Dateien spielen, wenn Sie Builds wie ausführen npm run build.


Fügen Sie als zusätzlichen Komfort das Profil bash_profile oder zsh hinzu.
Tropicalrambler vor

24

Ich habe dieses Problem beim Debuggen mit VSCode festgestellt. Ich wollte nur hinzufügen, dass Sie das Argument auf diese Weise zu Ihrem Debug-Setup hinzufügen können.

Sie können es der runtimeArgsEigenschaft Ihrer Konfiguration in hinzufügen launch.json.

Siehe Beispiel unten.

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

Im Folgenden finden Sie einige Flag-Werte, mit denen Sie zusätzliche Informationen dazu hinzufügen können, wie Sie beim Starten Ihres Knotenservers mehr Speicher zulassen.

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 

Kann man es in Potenzen von 2 weiter erhöhen? sollte man es größer als den Systemspeicher einstellen? Wenn nicht, was ist ein gutes Verhältnis von Systemspeicher zu maximaler Speicherplatzgröße?
Harry Moreno

3
@HarryMoreno Sie können tatsächlich einen beliebigen Zahlenwert eingeben. Muss nicht in der Potenz von 2 sein. Ich bin mir jedoch nicht sicher über das Verhältnis. Es ist nur eine maximale Grenze, es wird nicht der gesamte Speicher verwendet. Ich würde es einfach so hoch einstellen, wie Sie es brauchen, und es dann bei Bedarf verkleinern.
Nicholas Porter

Ich werde System RAM - 1 GB versuchen. Angenommen, diese VM dient nur zum Ausführen dieser Knoten-App.
Harry Moreno

2
@HarryMoreno Ein gutes Verhältnis von Systemspeicher zu maximaler Speicherplatzgröße hängt ganz davon ab, was sonst noch auf Ihrem Computer ausgeführt wird. Sie können es in Zweierpotenzen erhöhen - oder Sie können eine beliebige Zahl verwenden. Sie können es größer als den Systemspeicher einstellen - aber Sie werden auf Swap-Probleme stoßen.
Gigimoi

20

Ich hatte damit zu kämpfen, selbst nachdem ich --max-old-space-size eingestellt hatte.

Dann wurde mir klar, dass ich Optionen - max-old-space-size - vor das Karma-Skript stellen muss.

Geben Sie am besten beide Syntaxen an: - max-old-space-size und --max_old_space_size. Mein Skript für 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

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


5
" Am besten geben Sie beide Syntaxen an - max-old-space-size und --max_old_space_size " - Sie müssen dies nicht tun, sie sind Synonyme. Von nodejs.org/api/cli.html#cli_options : "Alle Optionen, einschließlich V8-Optionen, ermöglichen die Trennung von Wörtern durch Bindestriche (-) oder Unterstriche (_)."
ZachB

6
Die maximale Größe der ausführbaren Datei wurde entfernt und endet mit einem Fehler, wenn sie verwendet wird: github.com/nodejs/node/issues/13341
Crashbus

Ich musste es schneiden --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizeund es funktionierte
Sergey Pleshakov


11

fwiw, das Finden und Reparieren eines Gedächtnisschweins mit so etwas wie memwatch könnte helfen.


10

Schritte zur Behebung dieses Problems (unter Windows) -

  1. Öffnen Sie die Eingabeaufforderung und geben Sie %appdata%die Eingabetaste ein
  2. Navigieren Sie zum %appdata%Ordner> npm
  3. Öffnen oder bearbeiten ng.cmd in Ihrem bevorzugten Editor
  4. In --max_old_space_size=8192zum IF und ELSE - Block

Ihre node.cmdDatei sieht nach der Änderung folgendermaßen aus:

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

Dies ist Windows-spezifisch. Das OP erwähnte nichts über Windows.
Dan Dascalescu

@ DanDascalescu Aktualisierte Antwort. Vielen Dank für die Benachrichtigung
Umang Patwa

6

Die folgende Umgebungsvariable kann verwendet werden:

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

Noch ein Hinweis: console.log() verbraucht auch Speicher im Terminal.

Ich habe gerade versucht, die console.log () auf dem Terminal zu kommentieren. denn das wird auch Speicher brauchen.


6
Ist das eine Antwort oder ein Kommentar zu einer Antwort? Es gibt viele Antworten mitNODE_OPTIONS= --max-old-space-size=somesize
Barbansan

5

Wenn Sie den Speicher für Knoten (Fenster) global ändern möchten, gehen Sie zu Erweiterte Systemeinstellungen -> Umgebungsvariablen -> Neue Benutzervariable

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


4

Ich möchte nur hinzufügen, dass es in einigen Systemen --max-old-space-sizenicht ausreicht , das Knotenspeicherlimit zu erhöhen , und dass ein Betriebssystemfehler wie der folgende vorliegt:

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

In diesem Fall liegt dies wahrscheinlich daran, dass Sie die maximale mmap pro Prozess erreicht haben.

Sie können die max_map_count überprüfen, indem Sie ausführen

sysctl vm.max_map_count

und erhöhen Sie es durch Laufen

sysctl -w vm.max_map_count=655300

und beheben Sie es, dass es nach einem Neustart nicht zurückgesetzt wird, indem Sie diese Zeile hinzufügen

vm.max_map_count=655300

in /etc/sysctl.confDatei.

Überprüfen Sie hier für weitere Informationen.

Eine gute Methode zur Analyse des Fehlers besteht darin, den Prozess mit auszuführen strace

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

3

Ich habe vor kurzem das gleiche Problem gehabt und bin auf diesen Thread gestoßen, aber mein Problem war mit der ReactApp. Die folgenden Änderungen im Befehl zum Starten des Knotens haben meine Probleme behoben.

Syntax

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

Beispiel

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

Warum ist die Größe 16000 in der Größe des maximalen alten Raums?

Grundsätzlich hängt dies vom zugewiesenen Speicher für diesen Thread und Ihren Knoteneinstellungen ab.

Wie überprüfe und gebe ich die richtige Größe an?

Dies ist im Grunde in unserem Motor bleiben v8. Der folgende Code hilft Ihnen dabei, die Heap-Größe Ihrer lokalen Knoten-v8-Engine zu verstehen.

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

2

Ich hatte gerade das gleiche Problem mit meiner EC2-Instanz t2.micro, die 1 GB Speicher hat.

Ich habe das Problem behoben, indem ich eine Auslagerungsdatei mit dieser URL erstellt und die folgende Umgebungsvariable festgelegt habe.

export NODE_OPTIONS=--max_old_space_size=4096

Endlich ist das Problem weg.

Ich hoffe das wäre hilfreich für die Zukunft.


1

Nur für den Fall, dass es Menschen mit diesem Problem bei der Verwendung von NodeJS-Apps helfen kann, die eine hohe Protokollierung verursachen, hat ein Kollege dieses Problem gelöst, indem er die Standardausgabe (n) an eine Datei weitergeleitet hat.


1

Wenn Sie versuchen, nicht sich nodeselbst, sondern eine andere Software zu starten , webpackkönnen Sie beispielsweise die Umgebungsvariable und das Umgebungspaket verwenden cross-env:

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

1

Für die eckige Projektbündelung habe ich meiner pakage.json- Datei im Abschnitt " Skripte" die folgende Zeile hinzugefügt .

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

Um meinen Code zu bündeln, verwende ich npm run build-prodstattdessen anstelle vonng build --requiredFlagsHere

hoffe das hilft!


0

Aktualisieren Sie den Knoten auf die neueste Version. Ich war mit diesem Fehler auf Knoten 6.6 und habe auf 8.9.4 aktualisiert, und das Problem ist behoben.


0

In meinem Fall hatte ich eine npm installfrühere Version des Knotens ausgeführt. Nach einem Tag habe ich die Knotenversion und den RAM npm installfür einige Module aktualisiert . Danach bekam ich diesen Fehler. Um dieses Problem zu beheben, habe ich den Ordner node_module aus jedem Projekt gelöscht und ausgeführtnpm install erneut ausgeführt.

Hoffe, dies könnte das Problem beheben.

Hinweis: Dies geschah auf meinem lokalen Computer und wurde nur auf dem lokalen Computer behoben.


0

Dieser Befehl funktioniert einwandfrei. Ich habe 8 GB RAM in meinem Laptop, also habe ich Größe = 8192 eingestellt. Es dreht sich alles um RAM und außerdem müssen Sie den Dateinamen festlegen. Ich führe den Befehl npm run build aus , deshalb habe ich build.js verwendet .

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

0

In meinem Fall habe ich die Version von node.js auf die neueste Version aktualisiert und es hat wie ein Zauber funktioniert.


Hallo Angela und willkommen bei SO! Könnten Sie vielleicht die genaue Version von Node.js angeben, auf die Sie für zukünftige Leser aktualisiert haben? Vielen Dank!
kant312

Ich habe auf die neueste LTS-Version aktualisiert: 12.18.0
Angela Rana
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.