Mémoire Node.js insuffisante

248

Aujourd'hui, j'ai exécuté mon script pour l'indexation du système de fichiers pour actualiser l'index des fichiers RAID et après 4h, il s'est écrasé avec l'erreur suivante:

[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

Le serveur est équipé de 16 Go de RAM et de 24 Go de swap SSD. Je doute fortement que mon script ait dépassé 36 Go de mémoire. Au moins ça ne devrait pas

Le script crée un index des fichiers stockés en tant que tableau d'objets avec des métadonnées de fichiers (dates de modification, autorisations, etc., pas de big data)

Voici le code de script complet: http://pastebin.com/mjaD76c3

J'ai déjà rencontré des problèmes de nœuds étranges dans le passé avec ce script, ce qui m'a forcé, par exemple. diviser l'index en plusieurs fichiers comme le nœud était en panne lors du travail sur des fichiers volumineux tels que String. Existe-t-il un moyen d'améliorer la gestion de la mémoire de nodejs avec d'énormes ensembles de données?

Lapsio
la source

Réponses:

316

Si je me souviens bien, il existe une limite standard stricte pour l'utilisation de la mémoire dans le V8 d'environ 1,7 Go, si vous ne l'augmentez pas manuellement.

Dans l'un de nos produits, nous avons suivi cette solution dans notre script de déploiement:

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

Il y aurait également une nouvelle commande d'espace, mais comme je l'ai lu ici: a-tour-of-v8-garbage-collection le nouvel espace ne collecte que les données à court terme nouvellement créées et l'ancien espace contient toutes les structures de données référencées qui devraient être dans votre cas la meilleure option.

Felix
la source
De la même manière cette config est pour nodejs indépendamment sur le framework. @ Simer
Felix
Je développe avec angular 4 et j'obtiens le même problème, quel devrait être le fichier yourFile.js pour l'application angular?
Vikram
@VikramSingh utilisez-vous ng serveou distribuez-vous le résultat du ng builddossier / dist par un autre serveur Web comme express? Mais si votre projet Angular utilise plus que la mémoire standard de 1,7 Go, vous aurez peut-être un problème architectural dans votre application? Il semblerait que vous utilisiez le développement env avec nmp start, c'est peut-être une solution pour cela github.com/mgechev/angular-seed/issues/2063
Felix
J'utilise ng build avec angular cli et aot (dossier dist)
Vikram
2
index, fichier js @Techdive que vous utilisez pour démarrer le serveur
Basit
78

Juste au cas où quelqu'un se heurterait à cela dans un environnement où il ne peut pas définir directement les propriétés du nœud (dans mon cas, un outil de construction):

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

Vous pouvez définir les options de nœud à l'aide d'une variable d'environnement si vous ne pouvez pas les transmettre sur la ligne de commande.

Kamiel Wanrooij
la source
Pouvez-vous expliquer ce que vous voulez dire lorsque vous dites "... définissez les options de nœud à l'aide d'une variable d'environnement .."?
Keselme
6
@Keselme Une variable d'environnement est une variable qui a été définie sur le serveur à partir de laquelle tous les processus peuvent lire les données. Ouvrez un terminal SSH sur votre serveur et tapez: MY_VAR = bonjour puis tapez: echo $ MY_VAR. Vous verrez qu'il imprime "bonjour" dans le terminal. Vous venez de définir une variable d'environnement et de la relire.
Rob Evans
travaillé sur Ubuntu 18.04, vient d'ajouter la commande d'exportation à mon fichier bashrc
Rahal Kanishka
76

Si vous souhaitez augmenter l'utilisation de la mémoire du nœud à l'échelle mondiale - pas seulement un seul script, vous pouvez exporter une variable d'environnement, comme ceci:
export NODE_OPTIONS=--max_old_space_size=4096

Ensuite, vous n'avez pas besoin de jouer avec des fichiers lors de l'exécution de builds comme npm run build.

Maksim Luzik
la source
1
Pour plus de commodité, ajoutez au profil bash_profile ou zsh.
Tropicalrambler
24

J'ai rencontré ce problème lors de la tentative de débogage avec VSCode, je voulais simplement ajouter ceci est la façon dont vous pouvez ajouter l'argument à votre configuration de débogage.

Vous pouvez l'ajouter à la runtimeArgspropriété de votre configuration dans launch.json.

Voir l'exemple ci-dessous.

{
"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-o
la source
21

Voici quelques valeurs d'indicateur pour ajouter des informations supplémentaires sur la façon d'autoriser plus de mémoire lorsque vous démarrez votre serveur de noeud.

1 Go - 8 Go

#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 

Nicholas Porter
la source
peut-on continuer à l'augmenter en puissances de 2? faut-il la définir plus grande que la mémoire système? sinon, quel est le bon rapport mémoire système / taille max-old-space-size?
Harry Moreno
3
@HarryMoreno Vous pouvez réellement mettre n'importe quelle valeur numérique que vous aimez. Ne doit pas nécessairement avoir une puissance de 2. Je ne suis pas sûr du rapport cependant. Ce n'est qu'une limite maximale, il n'utilisera pas toute la mémoire. Je voudrais simplement le régler aussi haut que vous le souhaitez, puis le réduire si nécessaire.
Nicholas Porter
Je vais essayer le système ram - 1 Go. En supposant que ce vm sert uniquement à exécuter cette application de nœud.
Harry Moreno
2
@HarryMoreno Un bon rapport mémoire système / taille maximale de l'ancien espace dépend entièrement de ce qui s'exécute sur votre machine. Vous pouvez l'augmenter en puissances de deux - ou vous pouvez utiliser n'importe quel nombre. Vous pouvez la définir plus grande que la mémoire système - mais vous rencontrerez des problèmes de swap.
Gigimoi
20

je me débattais avec cela même après avoir défini --max-old-space-size.

Ensuite, j'ai réalisé le besoin de mettre des options --max-old-space-size avant le script karma.

il est également préférable de spécifier les deux syntaxes --max-old-space-size et --max_old_space_size mon script pour le 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

référence https://github.com/angular/angular-cli/issues/1652

duchuy
la source
5
" préférable de spécifier les deux syntaxes --max-old-space-size et --max_old_space_size " - vous n'avez pas besoin de le faire, ce sont des synonymes. De nodejs.org/api/cli.html#cli_options : "Toutes les options, y compris les options V8, permettent de séparer les mots par des tirets (-) ou des traits de soulignement (_)."
ZachB
6
max-executable-size a été supprimé et se termine par une erreur lors de son utilisation: github.com/nodejs/node/issues/13341
crashbus
J'ai dû le couper --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizeet cela a fonctionné
Sergey Pleshakov
16

J'ai eu un problème similaire lors de la construction angulaire AOT. Les commandes suivantes m'ont aidé.

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

Source: https://geeklearning.io/angular-aot-webpack-memory-trick/

Chandru
la source
1
Des cris de joie ont fonctionné pour moi, il peut être nécessaire desudo npm -g install increase-memory-limit --unsafe-perm
Leo
11

fwiw, trouver et réparer un porc de mémoire avec quelque chose comme memwatch pourrait aider.

NathanQ
la source
10

Étapes pour résoudre ce problème (sous Windows) -

  1. Ouvrez l'invite de commande et tapez %appdata%appuyez sur Entrée
  2. Accédez à %appdata%> dossier npm
  3. Ouvrez ou modifiez ng.cmddans votre éditeur préféré
  4. Ajouter --max_old_space_size=8192au bloc IF et ELSE

Votre node.cmdfichier ressemble à ceci après le changement:

@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" %*
)
Umang Patwa
la source
Ceci est spécifique à Windows. L'OP n'a rien mentionné sur Windows.
Dan Dascalescu
@DanDascalescu Réponse mise à jour. Merci d'avoir signalé
Umang Patwa
6

La variable d'environnement suivante peut être utilisée:

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

Autre remarque: console.log()consomme également de la mémoire dans le terminal.

juste essayé de commenter la console.log () sur le terminal. car cela prendra aussi de la mémoire.

Amar Powar
la source
6
Est-ce une réponse ou un commentaire à une réponse? Il y a beaucoup de réponses avecNODE_OPTIONS= --max-old-space-size=somesize
barbsan
5

si vous voulez changer la mémoire globalement pour le noeud (windows) allez dans paramètres système avancés -> variables d'environnement -> nouvelle variable utilisateur

variable name = NODE_OPTIONS
variable value = --max-old-space-size=4096
Ahmed Aboud
la source
4

J'ai essayé 👍 le code ci-dessous et son bon fonctionnement✌.

  • ouvrir le terminal depuis le répertoire racine du projet
  • exécutez la cmd pour définir une nouvelle taille.

    set NODE_OPTIONS=--max_old_space_size=8172

Ou vous pouvez consulter le lien pour plus d'informations https://github.com/nodejs/node/issues/10137#issuecomment-487255987

rkumar1904
la source
4

Je veux juste ajouter que dans certains systèmes, même en augmentant la limite de mémoire du nœud avec --max-old-space-size, ce n'est pas suffisant et il y a une erreur de système d'exploitation comme celle-ci:

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

Dans ce cas, c'est probablement parce que vous avez atteint le mmap max par processus.

Vous pouvez vérifier le max_map_count en exécutant

sysctl vm.max_map_count

et l'augmenter en exécutant

sysctl -w vm.max_map_count=655300

et corrigez-le pour qu'il ne soit pas réinitialisé après un redémarrage en ajoutant cette ligne

vm.max_map_count=655300

dans le /etc/sysctl.confdossier.

Cliquez ici pour plus d'informations.

Une bonne méthode pour analyser l'erreur consiste à exécuter le processus avec strace

strace node --max-old-space-size=128000 my_memory_consuming_process.js
jbaylina
la source
3

J'ai rencontré ce même problème récemment et suis tombé sur ce sujet, mais mon problème était avec ReactApp. Les modifications ci-dessous dans la commande de démarrage du nœud ont résolu mes problèmes.

Syntaxe

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

Exemple

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

Pourquoi la taille est 16000 en taille max-old-space?

Fondamentalement, cela dépend de la mémoire allouée à ce thread et des paramètres de votre nœud.

Comment vérifier et donner la bonne taille?

C'est essentiellement rester dans notre moteur v8. le code ci-dessous vous aide à comprendre la taille de segment de mémoire de votre moteur de nœud 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);
Venkat.R
la source
2

Je viens de rencontrer le même problème avec mon instance EC2 t2.micro qui a 1 Go de mémoire.

J'ai résolu le problème en créant un fichier d'échange à l'aide de cette URL et en définissant la variable d'environnement suivante.

export NODE_OPTIONS=--max_old_space_size=4096

Enfin, le problème a disparu.

J'espère que ce serait utile pour l'avenir.

Bat-Orshikh Baavgaikhuu
la source
1

Juste au cas où cela pourrait aider les personnes ayant ce problème lors de l'utilisation des applications nodejs qui produisent une journalisation intensive, un collègue a résolu ce problème en redirigeant les sorties standard vers un fichier.

Adrien Joly
la source
1

Si vous essayez de lancer non pas nodelui-même, mais un autre logiciel , par exemple, webpackvous pouvez utiliser la variable d'environnement et le cross-envpackage:

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

Pour le regroupement angulaire de projets, j'ai ajouté la ligne ci-dessous à mon fichier pakage.json dans la section des scripts .

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

Maintenant, pour regrouper mon code, j'utilise npm run build-prodau lieu deng build --requiredFlagsHere

J'espère que cela t'aides!

rgantla
la source
0

Mettez à niveau le nœud vers la dernière version. J'étais sur le noeud 6.6 avec cette erreur et mis à niveau vers 8.9.4 et le problème a disparu.

Richard Frank
la source
0

Dans mon cas, j'avais exécuté la npm installversion précédente du nœud, après un certain jour, j'ai mis à niveau la version du nœud et le ram npm installpour quelques modules. Après cela, j'obtenais cette erreur. Pour résoudre ce problème, j'ai supprimé le dossier node_module de chaque projet et j'ai exécuté à npm installnouveau.

J'espère que cela pourrait résoudre le problème.

Remarque: cela se produisait sur ma machine locale et cela a été corrigé sur la machine locale uniquement.

Gampesh
la source
0

Cette commande fonctionne parfaitement. J'ai 8 Go de RAM dans mon ordinateur portable, j'ai donc défini la taille = 8192. Il s'agit de ram et vous devez également définir un nom de fichier. Je lance l' exécution build NPM commande qui est la raison pour laquelle je build.js .

node --expose-gc --max-old-space-size=8192 node_modules/react-scripts/scripts/build.js
Taha Farooqui
la source
0

Dans mon cas, j'ai mis à niveau la version node.js vers la dernière et cela a fonctionné comme un charme.

Angela Rana
la source
Bonjour Angela et bienvenue à SO! Pourriez-vous peut-être spécifier la version exacte de Node.js que vous avez mise à jour pour les futurs lecteurs? Merci!
kant312
J'ai mis à niveau vers la dernière version LTS: 12.18.0
Angela Rana