Node.js堆内存不足

Lap*_*sio 195 javascript crash heap-memory out-of-memory node.js

今天我运行我的脚本进行文件系统索引以刷新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
Run Code Online (Sandbox Code Playgroud)

服务器配备16GB RAM和24GB SSD交换.我非常怀疑我的脚本超过36GB的内存.至少它不应该

脚本创建存储为具有文件元数据的对象数组的文件索引(修改日期,权限等,没有大数据)

这是完整的脚本代码:http: //pastebin.com/mjaD76c3

我已经在过去使用这个脚本遇到了奇怪的节点问题,这迫使我如此.将索引拆分成多个文件,因为当处理像String这样的大文件时,节点会出现故障.有没有办法用庞大的数据集改进nodejs内存管理?

小智 256

如果我没记错的话,如果不手动增加,则V8中的内存使用量有一个严格的标准限制,大约为1.7 GB.

在我们的一个产品中,我们在部署脚本中遵循了此解决方案:

 node --max-old-space-size=4096 yourFile.js
Run Code Online (Sandbox Code Playgroud)

还有一个新的空间命令,但正如我在这里读到的:a-tour-of-v8-garbage-collection新空间仅收集新创建的短期数据,旧空间包含所有应引入的数据结构你的情况是最好的选择.

  • 我正在使用 angular 4 进行开发并遇到同样的问题,angular 应用程序的 yourFile.js 文件应该是什么? (6认同)
  • 哪个文件放在 yourFile.js 中?Nodemon 文件或 NodeJS 文件? (5认同)
  • 用于启动服务器的index,js文件@Techdive (2认同)

Kam*_*oij 47

万一有人在一个他们无法直接设置节点属性的环境中遇到这种情况(在我的例子中是一个构建工具):

NODE_OPTIONS="--max-old-space-size=4096" node ...
Run Code Online (Sandbox Code Playgroud)

如果无法在命令行上传递节点选项,则可以使用环境变量设置节点选项.

  • 当您说“...使用环境变量设置节点选项..”时,您能解释一下您的意思吗? (4认同)
  • @Keselme环境变量是已在服务器上设置的变量,所有进程均可从中读取数据。打开服务器的SSH终端,然后键入:MY_VAR = hello,然后键入:echo $ MY_VAR。您会看到它在终端上显示“ hello”。您只需设置一个环境变量,然后将其读回即可。 (2认同)

Mak*_*zik 43

如果要全局增加节点的内存使用量 - 不仅是单个脚本,还可以导出环境变量,如下所示:
export NODE_OPTIONS=--max_old_space_size=4096

然后,在运行类似的构建时,您不需要使用文件 npm run build.

  • 为了更加方便,请添加到 bash_profile 或 zsh 配置文件。 (2认同)
  • @AyeshWeerasinghe 可能您正在使用或运行的库或脚本有一个硬编码的“max_old_space_size”参数,该参数会覆盖导出的环境变量。 (2认同)

小智 34

我的 EC2 实例 t2.micro 遇到了同样的问题,它有 1 GB 内存。

我通过使用url创建交换文件并设置以下环境变量来解决该问题。

export NODE_OPTIONS=--max_old_space_size=4096

终于问题解决了。

我希望这对未来有帮助。

  • 谢谢。在创建了 2GB 交换文件并将“ENV NODE_OPTIONS=--max_old_space_size=1024”添加到我的 Dockerfile 后,我现在可以在 5 美元/月的 Linode nanode 实例上“纱线构建”Strapi。不确定我的情况是否需要交换步骤,但这不会有什么坏处。 (3认同)

小智 22

我在尝试使用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"
        ]
    }
]}
Run Code Online (Sandbox Code Playgroud)

  • launch.json 与 package.json 相同吗? (2认同)

小智 16

在设置了--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
Run Code Online (Sandbox Code Playgroud)

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

  • max-executable-size已删除,使用时以错误结尾:https://github.com/nodejs/node/issues/13341 (4认同)
  • "*最好指定两种语法--max-old-space-size和--max_old_space_size*" - 您不需要这样做,它们是同义词.来自https://nodejs.org/api/cli.html#cli_options:"所有选项,包括V8选项,允许单词用短划线( - )或下划线(_)分隔." (3认同)

Nic*_*ter 14

这是一些标志值,用于添加有关在启动节点服务器时如何允许更多内存的其他信息。

1GB-8GB

#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 

Run Code Online (Sandbox Code Playgroud)

  • @HarryMoreno 您实际上可以输入您喜欢的任何数值。不必是 2 的幂。不过不确定比率。这只是一个最大限制,它不会使用所有内存。我会将它设置为您需要的高度,然后在需要时缩减。 (5认同)
  • @HarryMoreno 良好的系统内存与最大旧空间大小的比率完全取决于计算机上运行的其他内容。您可以将其增加到 2 的幂 - 或者您可以使用任何数字。您可以将其设置为大于系统内存 - 但您会遇到交换问题。 (2认同)

小智 12

在进行AOT角度构建时我遇到了类似的问题.以下命令帮助了我.

npm install -g increase-memory-limit
increase-memory-limit
Run Code Online (Sandbox Code Playgroud)

资料来源:https://geeklearning.io/angular-aot-webpack-memory-trick/


Ven*_*t.R 12

我最近遇到了同样的问题并遇到了这个线程,但我的问题出在ReactApp. node start 命令中的以下更改解决了我的问题。

句法

node --max-old-space-size=<size> path-to/fileName.js
Run Code Online (Sandbox Code Playgroud)

例子

node --max-old-space-size=16000 scripts/build.js
Run Code Online (Sandbox Code Playgroud)

为什么 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);
Run Code Online (Sandbox Code Playgroud)


小智 11

最近,在我的一个项目中遇到了同样的问题。尝试了一些任何人都可以尝试作为调试来确定根本原因的事情:

  1. 正如大家所建议的,通过添加以下命令来增加节点中的内存限制:

    {
       "scripts":{
          "server":"node --max-old-space-size={size-value} server/index.js"
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)

这里size-value我为我的应用程序定义的是 1536 (因为我的 kubernetes pod 内存限制为 2 GB,请求 1.5 GB)

因此,始终size-value根据您的前端基础设施/架构限制(略小于限制)来定义

在上面的命令中,有一个严格的标注,在命令--max-old-space-size之后使用node,而不是在文件名之后使用server/index.js

  1. 如果您有ngnix配置文件,请检查以下内容:

    • worker_connections:(16384对于繁重的前端应用程序)[nginx默认是512每个连接数worker,这对于现代应用程序来说太低了]

    • 使用:(epoll高效方法)【nginx支持多种连接处理方式】

    • http:添加以下内容以使您的工作人员免于忙于处理一些不需要的任务。(client_body_timeout , reset_timeout_connection , client_header_timeout , keepalive_timeout , send_timeout)。

  2. 删除所有日志记录/跟踪工具,例如APM , Kafka , UTM tracking, Prerender(SEO)等中间件或关闭。

  3. 现在代码级调试:在主server文件中,删除不需要的console.log仅打印消息的内容。

  4. 现在检查每个服务器路由,即app.get() , app.post() ...以下情况:

  • data => if(data) res.send(data)// 你真的需要等待数据还是 api 返回一些我必须等待的响应?,如果没有则修改如下:
data => res.send(data) // this will not block your thread, apply everywhere where it's needed
Run Code Online (Sandbox Code Playgroud)
  • else 部分:如果没有出现错误,那么简单地说return res.send({})NO console.log here

  • 错误部分:有些人定义为error或 ,err这会造成混乱和错误。像这样:

    `error => { next(err) } // here err is undefined`
    
     `err => {next(error) } // here error is undefined`
    
     `app.get(API , (re,res) =>{
         error => next(error) // here next is not defined
      })`
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用命令删除winston其他未使用的库。elastic-epm-nodenpx depcheck

  • 在 axios 服务文件中,检查方法和日志记录是否正确,如下所示:

      if(successCB) console.log("success") successCB(response.data) // here it's wrong statement, because on success you are just logging and then `successCB` sending  outside the if block which return in failure case also.
    
    Run Code Online (Sandbox Code Playgroud)
  • 避免stringify , parse在可访问的大型数据集上使用等。(我也可以在上面显示的日志中看到。

  1. 最后但并非最不重要的一点是,每次应用程序崩溃或 Pod 重新启动时,请检查日志。在日志中专门查找此部分:Security context 这将告诉您崩溃的原因、地点以及罪魁祸首。


Nat*_*anQ 10

fwiw,用memwatch之类的东西查找和修复记忆猪可能有所帮助.


jba*_*ina 10

我只想补充一点,在某些系统中,即使使用 增加节点内存限制--max-old-space-size,也是不够的,并且存在这样的操作系统错误:

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,可能是因为您达到了每个进程的最大 mmap。

您可以通过运行检查 max_map_count

sysctl vm.max_map_count
Run Code Online (Sandbox Code Playgroud)

并通过运行增加它

sysctl -w vm.max_map_count=655300
Run Code Online (Sandbox Code Playgroud)

并通过添加此行将其修复为在重新启动后不会重置

vm.max_map_count=655300
Run Code Online (Sandbox Code Playgroud)

/etc/sysctl.conf文件中。

点击这里获取更多信息。

分析错误的一个好方法是运行进程 strace

strace node --max-old-space-size=128000 my_memory_consuming_process.js
Run Code Online (Sandbox Code Playgroud)


can*_*nsu 10

我会提到两种类型的解决方案。

我的解决方案:就我而言,我将其添加到我的环境变量中:

export NODE_OPTIONS=--max_old_space_size=20480
Run Code Online (Sandbox Code Playgroud)

但即使我重新启动计算机,它仍然无法工作。我的项目文件夹位于 d:\ 磁盘中。所以我将我的项目删除到 c:\ 磁盘并且它工作了。

我队友的解决方案:package.json 配置也有效。

"start": "rimraf ./build && react-scripts --expose-gc --max_old_space_size=4096 start",
Run Code Online (Sandbox Code Playgroud)

  • 这有助于解决 github 操作中构建内存不足的问题。`“构建”:“react-scripts --expose-gc --max_old_space_size=4096 构建”,` (2认同)

小智 8

对于像我这样没有找到任何合适的解决方案的初学者,请检查安装的节点版本(x32、x64、x86)。我有一个 64 位 CPU,并且安装了 x86 节点版本,这导致了错误CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory


JSO*_*C11 8

--最大旧空间大小

Unix (苹果操作系统)

  1. 打开终端并使用nano打开我们的.zshrc文件,如下所示(这将创建一个,如果不存在)

    nano ~/.zshrc

  2. 通过将以下行添加到当前打开的.zshrc文件中来更新我们的NODE_OPTIONS环境变量:

    export NODE_OPTIONS=--max-old-space-size=8192 # increase node memory limit

请注意,只要我们的系统有足够的内存,我们就可以将传入的兆字节数设置为任意值(这里我们传入 8192 兆字节,大约为 8 GB)

  1. 按: 保存并退出 nano,ctrl + x然后y同意,最后enter保存更改。

  2. 关闭重新打开终端以确保我们的更改已被识别。

  3. 我们可以打印出.zshrc文件的内容来查看我们的更改是否已保存,如下所示cat ~/.zshrc

Linux (Ubuntu)

  1. 打开终端并使用nano打开.bashrc文件,如下所示:

    nano ~/.bashrc

其余步骤与上面的Mac步骤类似,但我们很可能~/.bashrc默认使用(而不是 ~/.zshrc)。所以这些值需要被替换!

Nodejs 文档链接


Uma*_*twa 7

解决步骤-

  1. 打开命令提示符,%appdata%然后按回车键
  2. 导航到%appdata%> npm文件夹
  3. ng.cmd在您喜欢的编辑器中打开或编辑
  4. 添加--max_old_space_size=8192到IF和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" %*
)
Run Code Online (Sandbox Code Playgroud)


Ahm*_*oud 5

如果要全局更改节点(Windows)的内存,请转到高级系统设置 -> 环境变量 -> 新用户变量

variable name = NODE_OPTIONS
variable value = --max-old-space-size=4096
Run Code Online (Sandbox Code Playgroud)


Fir*_*nks 5

您还可以使用以下命令更改 Window 的环境变量:

 $env:NODE_OPTIONS="--max-old-space-size=8192"
Run Code Online (Sandbox Code Playgroud)