Node.jsヒープのメモリ不足


245

今日、私はファイルシステムのインデックス作成用のスクリプトを実行してRAIDファイルのインデックスを更新し、4時間後に次のエラーでクラッシュしました。

[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

サーバーには16 GBのRAMと24 GBのSSDスワップが搭載されています。私のスクリプトがメモリの36GBを超えたのではないかと思います。少なくともそれはすべきではない

スクリプトは、ファイルのメタデータを含むオブジェクトの配列として保存されたファイルのインデックスを作成します(変更日、権限など、ビッグデータはありません)

ここに完全なスクリプトコードがあります:http : //pastebin.com/mjaD76c3

このスクリプトを使用して、過去に奇妙なノードの問題を経験しました。文字列などの大きなファイルで作業しているときにノードが誤作動していたため、インデックスを複数のファイルに分割しました。巨大なデータセットでnodejsのメモリ管理を改善する方法はありますか?

回答:


314

私が正しく覚えている場合、手動で増加しない場合、V8でのメモリ使用量には約1.7 GBの厳しい標準制限があります。

私たちの製品の1つでは、デプロイスクリプトでこのソリューションに従いました。

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

新しいスペースコマンドもありますが、ここで読んだように:a-tour-of-v8-garbage-collection新しいスペースは、新しく作成された短期データのみを収集し、古いスペースには、あなたのケースは最良の選択肢です。


同じように、この構成はフレームワーク上で独立してnodejs用です。@ Simer
Felix

私はangular 4で開発していて、同じ問題を抱えていますが、angularアプリのyourFile.jsファイルは何ですか?
Vikram

@VikramSinghを使用してng serveいますか、またはng build/ distフォルダの結果をExpressなどの別のWebサーバーで配布していますか?しかし、Angularプロジェクトが標準の1.7GBを超えるメモリを使用している場合、アプリケーションにアーキテクチャ上の問題がある可能性がありますか?nmp startで開発環境を使用しているようです。多分これはその解決策ですgithub.com/mgechev/angular-seed/issues/2063
Felix

Angular cliおよびaot(distフォルダー)でngビルドを使用しています
Vikram

2
サーバーの起動に使用するindex、jsファイル@Techdive
Basit

77

ノードプロパティを直接設定できない環境(私の場合はビルドツール)で誰かがこれに遭遇した場合に備えて:

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

コマンドラインで渡すことができない場合は、環境変数を使用してノードオプションを設定できます。


「...環境変数を使用してノードオプションを設定する...」と言ったときの意味を教えてください。
Keselme

6
@Keselme環境変数は、すべてのプロセスがデータを読み取ることができるサーバーで設定された変数です。サーバーへのSSHターミナルを開き、MY_VAR = helloと入力してから、echo $ MY_VARと入力します。ターミナルに "hello"と表示されることがわかります。環境変数を設定し、それを読み戻しました。
Rob Evans

Ubuntu 18.04で動作し、エクスポートコマンドをbashrcファイルに追加しました
Rahal Kanishka

76

ノードのメモリ使用量をグローバルに増やしたい場合-単一のスクリプトだけでなく、次のように環境変数をエクスポートできます。
export NODE_OPTIONS=--max_old_space_size=4096

そうすれば、のようなビルドを実行するときにファイルを操作する必要がなくなります npm run build


1
追加の便宜として、bash_profileまたはzshプロファイルに追加します。
トロピカル

24

VSCodeでデバッグしようとしたときにこの問題が発生したので、これを追加したいのは、デバッグセットアップに引数を追加する方法です。

あなたはそれをruntimeArgsあなたの設定のプロパティに追加することができますlaunch.json

以下の例を参照してください。

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

以下は、ノードサーバーの起動時にメモリを増やす方法に関する追加情報を追加するためのフラグ値です。

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 

2の累乗でそれを増やし続けることができますか?システムメモリよりも大きく設定すべきですか?システムメモリとmax-old-space-sizeの比率が適切でない場合
ハリーモレノ

3
@HarryMoreno実際には、好きな数値を入力できます。2の累乗である必要はありませんが、比率については不明です。これは上限にすぎず、すべてのメモリを使用することはありません。必要なだけ高く設定し、必要に応じて縮小します。
Nicholas Porter

システムRAMを1 GBで試します。このvmは、このノードアプリを実行するためだけのものであると想定しています。
ハリーモレノ

2
@HarryMorenoシステムメモリとmax-old-space-sizeの比率が適切かどうかは、マシンで他に何が実行されているかに完全に依存しています。2の累乗で増やすことができます-または任意の数を使用できます。システムメモリよりも大きく設定できますが、スワップの問題が発生します。
ジジモイ

20

--max-old-space-sizeを設定した後でも、これに苦労していました。

次に、カルマスクリプトの前にオプション--max-old-space-sizeを付ける必要があることに気付きました。

また、両方の構文--max-old-space-sizeと--max_old_space_sizeの両方の構文を指定して、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

参照https://github.com/angular/angular-cli/issues/1652


5
" --max-old-space-sizeと--max_old_space_sizeの両方の構文を指定するのが最善です-これを行う必要はありません。これらは同義語です。nodejs.org/api/cli.html#cli_optionsから:「V8オプションを含むすべてのオプションでは、単語をダッシュ​​(-)またはアンダースコア(_)の両方で区切ることができます。」
ZachB 2018年

6
max-executable-sizeが削除され、使用するとエラーで終了します:github.com/nodejs/node/issues/13341
crashbus

私はそれを切らなければならなかった、--max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizeそしてそれはうまくいった
セルゲイ・プレシャコフ'20



10

この問題を修正する手順(Windowsの場合)-

  1. コマンドプロンプトを開き、%appdata%Enter キーを押します
  2. 移動%appdata%> NPMフォルダ
  3. ng.cmdお気に入りのエディターで開くか編集します
  4. --max_old_space_size=8192IFおよびELSEブロックに追加

あなたのnode.cmdファイルは、変更後に次のようになります。

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

これはWindows固有です。OPはWindowsについては何も言及していません。
Dan Dascalescu、

@DanDascalescu回答を更新しました。通知ありがとう
Umang Patwa

6

次の環境変数を使用できます。

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

別のメモ:console.log()端末のメモリも消費します。

端末でconsole.log()をコメントしようとしたところです。それもメモリを必要とするからです。


6
これは、ある答えに対する答えですか、それともコメントですか?回答はたくさんありますNODE_OPTIONS= --max-old-space-size=somesize
barbsan

5

ノード(Windows)のメモリをグローバルに変更する場合は、システムの詳細設定->環境変数->新しいユーザー変数に移動します。

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


4

一部のシステムではそれを追加したいだけで、でノードのメモリ制限を増やしても、--max-old-space-size十分ではなく、次のようなOSエラーが発生します。

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

この場合、おそらくプロセスごとの最大mmapに達していることが原因です。

次のコマンドを実行すると、max_map_countを確認できます

sysctl vm.max_map_count

実行してそれを増やします

sysctl -w vm.max_map_count=655300

この行を追加して、再起動後にリセットされないように修正します

vm.max_map_count=655300

/etc/sysctl.confファイル。

ここをチェックをご覧ください。

エラーを分析する良い方法は、 strace

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

3

私は最近同じ問題に直面し、このスレッドに出くわしましたが、私の問題はReactアプリに関するものでした。以下のnode startコマンドの変更により、問題が解決しました。

構文

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

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

なぜサイズはmax-old-space-sizeで16000なのですか?

基本的には、そのスレッドに割り当てられたメモリとノードの設定によって異なります。

正しいサイズを確認して与える方法は?

これは基本的に私たちのエンジンにとどまりますv8。以下のコードは、ローカルノード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

1 GBのメモリを搭載したEC2インスタンスt2.microで同じ問題に直面しました。

この URLを使用してスワップファイルを作成し、次の環境変数を設定することで問題を解決しました。

export NODE_OPTIONS=--max_old_space_size=4096

ようやく問題が解決しました。

今後のお役に立てれば幸いです。


1

大量のログを生成するnodejsアプリを使用しているときにこの問題が発生する可能性がある場合に備えて、同僚が標準出力をファイルにパイプすることでこの問題を解決しました。


1

nodeそれ自体ではなく、他のソフトを起動しようとしている場合、たとえばwebpack、環境変数とcross-envパッケージを使用できます。

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

1

角度のプロジェクトバンドリングのために、私はきたにラインの下に追加私のpakage.json内のファイルのスクリプトのセクション。

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

今、私のコードをバンドルするためnpm run build-prodに、代わりにng build --requiredFlagsHere

お役に立てれば!


0

ノードを最新バージョンにアップグレードします。私はこのエラーでノード6.6にいて、8.9.4にアップグレードし、問題は解消しました。


0

私の場合npm install、以前のバージョンのノードで実行していましたが、ある日npm install、いくつかのモジュールのノードバージョンとRAMをアップグレードしました。この後、このエラーが発生しました。この問題を修正するために、各プロジェクトからnode_moduleフォルダーを削除して実行しましたnpm install再度しました。

これで問題が解決することを願っています。

注:これは私のローカルマシンで発生しており、ローカルマシンでのみ修正されました。


0

このコマンドは完全に機能します。私のラップトップには8GBのRAMがあるので、size = 8192を設定しました。それはすべてramに関するもので、ファイル名を設定する必要もあります。私はnpm run buildコマンドを実行するので、build.jsを使用しました

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

0

私の場合、node.jsのバージョンを最新にアップグレードしました。


アンジェラこんにちは、SOへようこそ!今後の読者のために更新したNode.jsの正確なバージョンを指定できますか?ありがとう!
kant312

最新のLTSバージョン12.18.0にアップグレードしました
アンジェララナ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.