Node.js堆内存不足

今天,我运行了文件系统索引的脚本来刷新RAID文件索引,4h后它崩溃了,出现以下错误:

[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

服务器配置16gb RAM和24gb SSD交换盘。我非常怀疑我的脚本内存超过了36gb。至少不应该是这样

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

以下是完整的脚本代码: http://pastebin.com/mjaD76c3 < / p >

我已经经历了奇怪的节点问题在过去与这个脚本迫使我eg。分割索引到多个文件作为节点是故障时,工作在这样的大文件字符串。对于庞大的数据集,有什么方法可以改善nodejs的内存管理吗?

783304 次浏览

如果我没记错的话,V8的内存使用有一个严格的标准限制,大约是1.7 GB,如果你不手动增加它的话。

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

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

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

我遇到这个问题时,试图调试与VSCode,所以只是想添加这是如何添加参数到您的调试设置。

你可以将它添加到你在launch.json中的配置的runtimeArgs属性。

参见下面的示例。

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

即使在设置max-old-space-size后,我也在努力解决这个问题。

然后我意识到需要把选项——max-old-space-size放在业力脚本之前。

最好同时指定语法——max-old-space-size和——max_old_space_size my script for 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

将节点升级到最新版本。我在6.6节点上出现了这个错误,并升级到8.9.4,问题消失了。

为了防止人们在使用产生大量日志记录的nodejs应用程序时遇到这个问题,一位同事通过将标准输出管道到一个文件来解决这个问题。

我在做AOT角构建时也遇到了类似的问题。听从命令帮助了我。

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

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

为了防止任何人在不能直接设置节点属性的环境中遇到这个问题(在我的情况下是构建工具):

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

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

修复此问题的步骤(在Windows) -

  1. 打开命令提示符并输入%appdata%按enter
  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" %*
)

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

那么你不需要在运行构建时使用文件 npm run build . < / p >

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

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


在我的情况下,我在以前版本的节点上运行了npm install,在某一天我升级了节点版本和内存npm install的几个模块。在这之后,我得到了这个错误。 为了解决这个问题,我从每个项目中删除了node_module文件夹,并再次运行npm install

希望这能解决问题。

注意:这发生在我的本地机器上,它只在本地机器上得到了修复。

如果你不是试图启动node本身,而是其他一些软的,例如webpack,你可以使用环境变量和cross-env包:

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

我最近也遇到了同样的问题,遇到了这个线程,但我的问题是React应用程序。下面节点开始命令的更改解决了我的问题。

语法

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);

如果你想更改节点(windows)的全局内存,请进入高级系统设置->环境变量->新用户变量

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

对于angular项目捆绑,我在脚本部分中添加了下面的行我的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

希望这能有所帮助!

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

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

我的EC2实例t2也遇到了同样的问题。微处理器,内存为1gb。

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

export NODE_OPTIONS=--max_old_space_size=4096

问题终于解决了。

我希望这对以后会有所帮助。

在我的例子中,我把node.js版本升级到最新版(12.8.0版本),它就像一个魅力。

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

你也可以用以下方法改变Window的环境变量:

 $env:NODE_OPTIONS="--max-old-space-size=8192"

对于Angular,这是我的修复方法

Package.json中,在script标记中添加这个

"scripts": {
"build-prod": "node --max_old_space_size=5048 ./node_modules/@angular/cli/bin/ng build --prod",
},

现在在terminal/cmd中不使用ng build --prod,只使用

npm run build-prod

如果你想为build使用这个配置,只需要从所有3个位置删除--prod

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

  1. 正如每个人建议的那样,通过添加以下命令来增加节点的内存限制:

    {
    "scripts":{
    "server":"node --max-old-space-size={size-value} server/index.js"
    }
    }
    

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

因此,始终根据前端基础设施/体系结构限制(略小于limit)定义size-value

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

  1. 如果你有ngnix配置文件,那么检查以下内容:

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

    • use: epoll(高效方法)[nginx支持多种连接处理方法]

    • 添加以下内容,将你的员工从处理一些不必要的任务中解放出来。(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
  • else部分:如果没有错误,则简单地return res.send({})没有 console.log here

  • 错误部分:一些人定义为errorerr,这造成了混淆和错误。是这样的:

    `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
    })`
    
  • 使用npx depcheck命令删除winstonelastic-epm-node其他未使用的库。

  • 在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.
    
  • 在访问大数据集上避免使用stringify , parse等。(我也可以在你上面显示的日志中看到。

  1. 最后但并非最不重要的是,每当应用程序崩溃或pod重新启动时,都要检查日志。在log中特别查找这个部分:Security context 这将给你为什么,在哪里,谁是崩溃背后的的罪魁祸首

使用选项--optimize-for-size。它将专注于使用更少的内存。

如果任何给出的答案都不适合你,检查你安装的节点是否与你的系统兼容(即32位或64位)。通常这种类型的错误发生是因为不兼容的节点和操作系统版本,终端/系统不会告诉你,但会让你给出内存不足的错误。

如果内存或RAM有限,则执行以下命令。

Ng serve——source-map=false

它将能够启动应用程序。在我的例子中,它需要16gb内存。但我可以用8gb内存运行。

检查是否没有在64位计算机上安装32位版本的节点。如果你在64位或32位机器上运行node,那么nodejs文件夹应该分别位于Program Files和Program Files (x86)中。

我将提到两种解决方案。

我的解决方案:在我的例子中,我将这个添加到我的环境变量:

export NODE_OPTIONS=--max_old_space_size=20480

但是即使我重新启动我的电脑,它仍然不能工作。我的项目文件夹在d:\ disk。所以我把我的项目移到c:\ disk,它工作了。

我队友的解决方案是:打包。Json配置也工作。

"start": "rimraf ./build && react-scripts --expose-gc --max_old_space_size=4096 start",

我在AWS Elastic Beanstalk上有这个错误,从t3升级实例类型。micro(免费层)到t3。小修正错误

——max-old-space-size .

Unix (Mac OS)

  1. 打开一个终端,使用纳米打开我们的. zshrc文件,像这样(这将创建一个,如果一个不存在):

    nano ~/.zshrc

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

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

请注意,只要我们的系统有足够的内存(这里我们传递的是8192兆字节,大约是8gb),我们可以将传入的兆字节数设置为我们喜欢的任何数。

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

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

  3. 我们可以打印出我们的. zshrc文件的内容,看看我们的更改是否像这样保存:

Linux (Ubuntu)

  1. 打开一个终端,使用纳米打开. bashrc文件,如下所示:

    nano ~/.bashrc

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

Nodejs Docs链接

我今天也遇到了同样的问题。对我来说,问题是,我试图在我的NextJS项目中导入大量数据到数据库。

所以我所做的是,我像这样安装win-node-env包:

yarn add win-node-env

因为我的开发机器是窗户。我在本地安装,而不是在全球安装。你也可以像这样全局安装它:yarn global add win-node-env

然后在我的NextJS项目的package.json文件中,我添加了另一个启动脚本,像这样:

"dev_more_mem": "NODE_OPTIONS=\"--max_old_space_size=8192\" next dev"

这里,我传递节点选项,即。设置8GB为上限。 所以我的package.json文件有点像这样:

{
"name": "my_project_name_here",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev_more_mem": "NODE_OPTIONS=\"--max_old_space_size=8192\" next dev",
"build": "next build",
"lint": "next lint"
},
......
}

然后我这样运行它:

yarn dev_more_mem

对我来说,我只在我的开发机器上遇到了这个问题(因为我正在导入大数据)。因此有了这个解决方案。我想分享一下,因为它可能对其他人有用。

我在一台windows机器上也有同样的问题,我注意到出于某种原因,它在git bash中不能工作,但在power shell中可以工作