我遇到堆内存错误,导致我的应用程序崩溃。但我的应用程序有可用内存。
app/web.1 [4:0x4ea2840] 27490 ms: Mark-sweep 505.7 (522.4) -> 502.2 (523.1) MB, 440.3 / 0.0 ms (average mu = 0.280, current mu = 0.148) allocation failure scavenge might not succeed
app/web.1 FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
错误发生在 512mb 左右。我的标准 2X dyno 有 1GB。
节点版本为16.17.0。据我了解,超过 12 的节点版本的堆限制基于可用内存。
>= 12 的 Node 版本可能不需要使用 --optimize_for_size 和 --max_old_space_size 标志,因为 JavaScript 堆限制将基于可用内存。 源
我考虑了 512mb 测功机上的一名工人。但是worker dyno会导致整个应用程序崩溃吗?如果是这样的话,错误不是来自
app/worker.1
而不是像日志中所示的 app/web.1
吗?
我想出了如何重新创建堆限制分配错误。这让我获得了更多线索。
我在 512mb 爱好测功机上在 256mb 左右收到错误。
我在 1024mb(1gb) 标准 2X 上大约 512mb 处收到错误。
所以它始终是可用内存的一半。我不确定这是否是 heroku 上的某种设置。
使用 v8 节点模块(包含在节点中)我可以获得更多数据:
const v8 = require('v8');
// added the code below to a route that caused a memory leak
const heapStats = v8.getHeapStatistics();
const heapStatsMB = heapStats;
for (const key in heapStatsMB) {
heapStatsMB[key] = `${(((heapStatsMB[key] / 1024 / 1024) * 100) / 100).toFixed(2)} MB`;
}
console.table(heapStatsMB);
我可以看到
heap_size_limit
在爱好测功机上为 259,在 2X 标准测功机上为 515。
┌─────────────────────────────┬─────────────┐
│ (index) │ Values │
├─────────────────────────────┼─────────────┤
│ total_heap_size │ '268.08 MB' │
│ total_heap_size_executable │ '2.25 MB' │
│ total_physical_size │ '266.73 MB' │
│ total_available_size │ '3.31 MB' │
│ used_heap_size │ '263.69 MB' │
│ heap_size_limit │ '259.00 MB' │
│ malloced_memory │ '1.01 MB' │
│ peak_malloced_memory │ '3.03 MB' │
│ does_zap_garbage │ '0.00 MB' │
│ number_of_native_contexts │ '0.00 MB' │
│ number_of_detached_contexts │ '0.00 MB' │
│ total_global_handles_size │ '0.16 MB' │
│ used_global_handles_size │ '0.16 MB' │
│ external_memory │ '18.53 MB' │
└─────────────────────────────┴─────────────┘
--max-old-space-size=1024
进入 procfile。
web: node --max-old-space-size=1024 bin/www
或
添加环境变量键:
NODE_OPTIONS
,值为--max_old_space_size=1024
原来我的Procfile是
web: node --optimize_for_size bin/www
我有一个环境变量键
--max-old-space-size
,值 1024
。
这不是列出环境变量的正确方法。它应该是键:
NODE_OPTIONS
,值为 --max_old_space_size=1024
。我自己还没有尝试过。
相反,我将我的 procfile 更改为:
web: node --optimize_for_size --max-old-space-size=1024 bin/www
这也有效。
我不确定
--optimize_for_size
会做什么,因为 node bin/www
与 node --optimize_for_size bin/www
都根据测功机大小将 heap_size_limit
更改为大约相同的量。所以后来我把--optimize_for_size
拿出来了。