【问题标题】:Node.js heap out of memoryNode.js 堆内存不足
【发布时间】:2021-07-05 17:54:42
【问题描述】:

今天我运行我的文件系统索引脚本以​​刷新 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

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

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

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

过去我已经经历过奇怪的节点问题,这个脚本迫使我例如。将索引拆分为多个文件,因为在处理 String 等大文件时节点出现故障。有没有什么办法可以通过庞大的数据集来改进 nodejs 的内存管理?

【问题讨论】:

  • windows cmd:set NODE_OPTIONS=--max-old-space-size=8192

标签: javascript node.js crash out-of-memory heap-memory


【解决方案1】:

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

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

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

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

【讨论】:

  • 与此配置相同,此配置适用于框架上的 nodejs。@Simer
  • 我正在使用 angular 4 进行开发并遇到同样的问题,angular 应用程序的 yourFile.js 文件应该是什么?
  • @VikramSingh 您是在使用ng serve 还是将ng build 的结果分发到/dist 文件夹中?但是,如果您的 Angular 项目使用的内存超过标准的 1.7GB 内存,那么您的应用程序中可能会出现架构问题?看起来您正在使用带有 nmp start 的开发环境,也许这是它的解决方案github.com/mgechev/angular-seed/issues/2063
  • yourFile.js 中放入了哪个文件?? Nodemon 文件还是 NodeJS 文件?
  • index,js 文件 @Techdive 用于启动服务器
【解决方案2】:

如果你想全局增加节点的内存使用——不仅仅是单个脚本,你可以导出环境变量,像这样:
export NODE_OPTIONS=--max_old_space_size=4096

那么你在运行构建时就不需要玩文件了 npm run build.

【讨论】:

  • 为方便起见,添加到 bash_profile 或 zsh 配置文件中。
  • 即使将 NODE_OPTIONS 设置为 4096 或更多,我也会遇到同样的错误。当我运行命令npm run build 时,我看到一些进程使用usr/bin/node --max_old_space_size=2048 之类的命令运行。可能是什么原因?
  • @AyeshWeerasinghe 可能您正在使用或运行的库或脚本有一个硬编码的 max_old_space_size 参数,它会覆盖导出的环境变量。
【解决方案3】:

以防万一有人在无法直接设置节点属性的环境中遇到此问题(在我的情况下是构建工具):

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

如果无法在命令行中传递节点选项,可以使用环境变量设置它们。

【讨论】:

  • 您能否解释一下您的意思,当您说“...使用环境变量设置节点选项..”时?
  • @Keselme 环境变量是在服务器上设置的变量,所有进程都可以从中读取数据。打开一个 SSH 终端到您的服务器并输入:MY_VAR=hello 然后输入:echo $MY_VAR。您将看到它在终端中打印“hello”。您刚刚设置了一个环境变量并将其读回。
  • 在 Ubuntu 18.04 上工作,只是将导出命令添加到我的 bashrc 文件中
【解决方案4】:

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

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 

【讨论】:

  • 可以不断增加它的 2 次方吗?应该将其设置为大于系统内存吗?如果不是,什么是好的系统内存与最大旧空间大小的比率?
  • @HarryMoreno 实际上你可以输入任何你喜欢的数值。不必是 2 的幂。但不确定比率。这只是一个最大限制,它不会使用所有内存。我会将其设置为您需要的最高值,然后根据需要缩减。
  • 我会试试系统内存 - 1gb。假设此 vm 仅用于运行此节点应用程序。
  • @HarryMoreno 一个好的系统内存与最大旧空间大小的比率完全取决于您机器上运行的其他内容。您可以将其增加为 2 的幂 - 或者您可以使用任何数字。您可以将其设置为大于系统内存 - 但您会遇到交换问题。
【解决方案5】:

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

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

export NODE_OPTIONS=--max_old_space_size=4096

问题终于解决了。

希望对未来有所帮助。

【讨论】:

  • 感谢分享。我遇到了同样的问题,你的提示对我来说很好。
  • 谢谢。在我创建了一个 2GB 交换文件并向我的 Dockerfile 添加了一个“ENV NODE_OPTIONS=--max_old_space_size=1024”之后,我现在可以在我的 $5/mo Linode nanode 实例上“构建”Strapi。不确定在我的情况下是否需要交换步骤,但它不会受到伤害。
  • 太棒了!在 Azure Standard_B1s 为我工作
  • 没错,对于小型机器,您可能需要使其更小而不是更大,例如导出 NODE_OPTIONS=--max_old_space_size=1024
【解决方案6】:

我在尝试使用 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"
        ]
    }
]}

【讨论】:

  • launch.json 会和 package.json 一样吗?
  • 不,launch.json 是专门用于从 VS Code 运行应用程序的配置文件。
  • VS Code 的 launch.json 文件在哪里?
【解决方案7】:

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

然后我意识到需要将选项 --max-old-space-size 放在 karma 脚本之前。

最好同时指定语法 --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

【讨论】:

  • "最好同时指定语法 --max-old-space-size 和 --max_old_space_size" -- 你不需要这样做,它们是同义词。来自nodejs.org/api/cli.html#cli_options:“所有选项,包括 V8 选项,都允许用破折号 (-) 或下划线 (_) 分隔单词。”
  • max-executable-size 被移除,使用时报错:github.com/nodejs/node/issues/13341
  • 我不得不把它剪成--max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_size,它工作了
  • 谢谢,你绝对是救命稻草。 optimize-for-size 终于让我的构建成功了。
【解决方案8】:

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

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

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

【讨论】:

  • 干杯为我工作,可能有必要sudo npm -g install increase-memory-limit --unsafe-perm
  • 4k 是不够的。开发人员保持 4k 为静态。开发商的好解决方案。此外,当我浏览 npm 页面时,我看不到有关更改限制值的信息。实际上,有一个解决方案,但没有奏效。
  • 现在在 2021 年必须有更好的选择,因为该库被标记为已弃用:npmjs.com/package/increase-memory-limit
  • 运行后我输入npm run dev 并停在那里。在此行 &gt; webpack-dev-server --config ./webpack.dev.config.js 之后,它没有显示任何进展,也没有给出任何错误。它正在玩雕像,所以项目无法运行。
【解决方案9】:

解决此问题的步骤(在 Windows 中)-

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

【讨论】:

    【解决方案10】:

    我最近遇到了同样的问题并遇到了这个帖子,但我的问题是React App。以下节点启动命令的更改解决了我的问题。

    语法

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

    示例

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

    为什么 max-old-space-size 的 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);
    

    【讨论】:

      【解决方案11】:

      我只是想在某些系统中补充一点,甚至用--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 文件中。

      查看here了解更多信息。

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

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

      【讨论】:

        【解决方案12】:

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

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

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

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

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

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

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

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

          • 使用: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 =&gt; if(data) res.send(data) // 你真的需要等待数据还是那个 api 返回一些我必须等待的响应? , 如果没有则修改如下:
        data => res.send(data) // this will not block your thread, apply everywhere where it's needed
        
        • 其他部分:如果没有错误出现,那么只需 return res.send({})NO 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 重新启动时,请检查日志。在日志中专门查找此部分:Security context 这将告诉您为什么、在哪里以及谁是导致崩溃的罪魁祸首

        【讨论】:

          【解决方案13】:

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

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

          【讨论】:

            【解决方案14】:

            您还可以通过以下方式更改 Window 的环境变量:

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

            【讨论】:

              【解决方案15】:

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

              【讨论】:

                【解决方案16】:

                我会提到两种解决方案。

                我的解决方案:在我的情况下,我将其添加到我的环境变量中:

                export NODE_OPTIONS=--max_old_space_size=20480
                

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

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

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

                【讨论】:

                  【解决方案17】:

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

                  【讨论】:

                  • 你好安吉拉,欢迎来到 SO!您能否为未来的读者指定您更新到的 Node.js 的确切版本?谢谢!
                  • 我升级到最新的 LTS 版本:12.18.0
                  • 没想到这会奏效,但它确实奏效了!因此,对于阅读本文且他们的 Node 版本较旧的任何人,请尝试升级到最新版本(我从 10 版本升级到 14.8),它可能会为您解决此问题。非常感谢
                  【解决方案18】:

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

                  【讨论】:

                  • 这使我免于出现“分段错误”。非常感谢!
                  【解决方案19】:

                  此命令完美运行。我的笔记本电脑有 8GB 内存,所以我设置了 size=8192。这都是关于 ram 的,你还需要设置文件名。我运行 npm run build 命令,这就是我使用 build.js 的原因。

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

                  【讨论】:

                  • 您是否将所有可用内存分配给 node.js?我不知道您的环境的详细信息,但您应该考虑为操作系统或来宾操作系统和其他相关进程节省一些内存(以防万一)。
                  • @Ricardo 是的,分配所有内存,你是绝对正确的。顺便说一句,现在我有 32 GB 内存。
                  【解决方案20】:

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

                  【讨论】:

                    【解决方案21】:

                    以防万一它可以帮助人们在使用产生大量日志记录的 nodejs 应用程序时遇到此问题,一位同事通过将标准输出管道传输到文件来解决此问题。

                    【讨论】:

                      【解决方案22】:

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

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

                      【讨论】:

                        【解决方案23】:

                        对于 Angular 项目捆绑,我已将以下行添加到我的 pakage.json 文件的 scripts 部分。

                        "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

                        希望这会有所帮助!

                        【讨论】:

                          【解决方案24】:

                          对于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

                          【讨论】:

                            【解决方案25】:

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

                            希望这可以解决问题。

                            注意:这发生在我的本地机器上,并且仅在本地机器上得到修复。

                            【讨论】:

                              【解决方案26】:

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

                              【讨论】:

                                【解决方案27】:

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

                                ng 服务 --source-map=false

                                它将能够启动应用程序。对于我的示例,它需要 16gb RAM。但我可以使用 8GB RAM 运行。

                                【讨论】:

                                  【解决方案28】:

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

                                  【讨论】:

                                    【解决方案29】:

                                    我在 AWS Elastic Beanstalk 上遇到此错误,将实例类型从 t3.micro(免费套餐)升级到 t3.small 修复了该错误

                                    【讨论】:

                                      猜你喜欢
                                      • 2021-09-19
                                      • 1970-01-01
                                      • 2013-09-10
                                      • 2018-02-10
                                      • 2013-08-09
                                      • 2017-09-09
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多