28

我们在 node.js 上运行一个 XMPP 服务器,在一台大约 3.8 GB RAM 的机器上。以下是我们在调用节点时传递的命令行参数: /opt/node/bin/node --max-old-space-size=3000 --trace-gc --trace-gc-verbose main.js

然而,我们经常不得不在这个过程中看到超过 10 秒的 gc 暂停(有时超过 1 分钟的 gc 暂停,我们的服务器除了运行 GC 什么都不做)。发生这种情况时,我们的进程处于正常的内存消耗状态:大约 1 GB 堆使用量。该进程有大约 2 GB 或可用空间,但该进程只是不使用它,并花一分钟时间尝试释放内存。

查看 --trace-gc-verbose 选项给出的 gc 跟踪,看起来大约 2 GB 的可用空间被标记为“大对象空间”,并且没有使用,因为没有那么多大对象。尽管该进程迫切需要更多内存用于“旧指针”和“旧数据空间”,但并未使用来自“大对象空间”的空闲内存。

这是 gc 在进程中长时间 gc 暂停期间留下的痕迹:

    

91635809 ms: Mark-sweep 968.8 (1039.0) -> 958.5 (1038.0) MB, 1 / 410 ms (+ 2287 ms,自标记开始后的 79 步,最大步长 140.227051 ms) [idle notification: finalize incremental] [GC in old要求的空间]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已使用:192,可用:8388416
旧指针,已使用:633992112,可用:10460240,浪费:0
旧数据空间,已使用:315819248,可用:149776,浪费:0
代码空间,已用:5867936,可用:1271392,浪费:0
地图空间,已使用:10257976,可用:6384072,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91636499 毫秒:Scavenge 965.5 (1038.0) -> 964.6 (1038.0) MB,17 毫秒(自上次 GC 以来的 10 步中增加了 109 毫秒)[Runtime::PerformGC]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:41256,可用:2055896
旧指针,已使用:628458688,可用:15993664,浪费:0
旧数据空间,已使用:315821792,可用:147232,浪费:0
代码空间,已用:5904256,可用:1235072,浪费:0
地图空间,已使用:10263072,可用:6378976,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91637979 毫秒:Scavenge 966.6 (1038.0) -> 964.7 (1038.0) MB,1 毫秒(自上次 GC 以来的 43 步中增加了 1404 毫秒)[Runtime::PerformGC]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:76736,可用:2020416
旧指针,已使用:628458688,可用:15993664,浪费:0
旧数据空间,已使用:315845520,可用:123504,浪费:0
代码空间,已用:5980576,可用:1158752,浪费:0
地图空间,已使用:10271416,可用:6370632,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91639088 ms: Mark-sweep 965.2 (1038.0) -> 935.8 (1038.0) MB, 1 / 369 ms (+ 2235 ms in 71 steps since the start of marking, max step 69.053955 ms) [idle notification: finalize incremental] [GC in old要求的空间]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:168,可用:2096984
旧指针,已使用:641099768,可用:3352584,浪费:0
旧数据空间,已使用:315820152,可用:148872,浪费:0
代码空间,已用:5862976,可用:1276352,浪费:0
地图空间,已用:10256744,可用:6385304,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91640987 毫秒:Scavenge 966.4 (1038.0) -> 964.5 (1038.0) MB,1 毫秒(自上次 GC 以来的 36 步中增加了 1275 毫秒)[分配失败]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:100944,可用:1996208
旧指针,已使用:627957504,可用:16494848,浪费:0
旧数据空间,已使用:315830536,可用:138488,浪费:0
代码空间,已用:5951200,可用:1188128,浪费:0
地图空间,已使用:10266376,可用:6375672,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91641560 毫秒:Scavenge 966.5 (1038.0) -> 964.8 (1038.0) MB,2 毫秒(自上次 GC 以来的 29 步中增加了 481 毫秒)[Runtime::PerformGC]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已使用:180712,可用:1916440
旧指针,已使用:627957504,可用:16494848,浪费:0
旧数据空间,已使用:315871432,可用:97592,浪费:0
代码空间,已用:6019392,可用:1119936,浪费:0
地图空间,已用:10269848,可用:6372200,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91642589 ms: Mark-sweep 965.9 (1038.0) -> 947.7 (1038.0) MB, 1 / 371 ms (+ 2369 ms,自标记开始以来的 89 步,最大步长 67.302002 ms) [空闲通知:完成增量] [旧 GC要求的空间]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:264,可用:2096888
旧指针,已使用:639592840,可用:4859512,浪费:0
旧数据空间,已使用:315849408,可用:119616,浪费:0
代码空间,已用:5862976,可用:1276352,浪费:0
地图空间,已使用:10257136,可用:6384912,浪费:0
单元空间,已用:175936,可用:954304,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91643688 毫秒:Scavenge 966.4 (1038.0) -> 964.6 (1038.0) MB,5 毫秒(自上次 GC 以来的 21 个步骤中增加了 356 毫秒)[Runtime::PerformGC]。
内存分配器,使用:1088446464,可用:2124390400
新空间,已用:144088,可用:1953064
旧指针,已使用:627748368,可用:16703984,浪费:0
旧数据空间,已使用:315864504,可用:104520,浪费:0
代码空间,已用:5990240,可用:1149088,浪费:0
地图空间,已使用:10264248,可用:6377800,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2123325184
91645276 毫秒:Scavenge 966.5 (1038.0) -> 964.8 (1039.0) MB,2 毫秒(自上次 GC 以来的 46 步中增加了 1520 毫秒)[分配失败]。
内存分配器,使用:1089495040,可用:2123341824
新空间,已使用:108192,可用:1988960
旧指针,已使用:627748368,可用:16703984,浪费:0
旧数据空间,已使用:315978760,可用:1022200,浪费:0
代码空间,已用:6039008,可用:1100320,浪费:0
地图空间,已使用:10274216,可用:6367832,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2122276608
91645577 毫秒:Scavenge 966.6 (1039.0) -> 965.8 (1039.0) MB,3 毫秒(自上次 GC 以来的 23 步中增加了 263 毫秒)[分配失败]。
内存分配器,使用:1089495040,可用:2123341824
新空间,已用:516168,可用:1580984
旧指针,已使用:627843088,可用:16609264,浪费:0
旧数据空间,已使用:316550680,可用:450280,浪费:0
代码空间,已用:6039008,可用:1100320,浪费:0
地图空间,已使用:10275280,可用:6366768,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2122276608
91645645 毫秒:Scavenge 967.3 (1039.0) -> 966.8 (1039.0) MB,5 毫秒(自上次 GC 以来的 16 步中增加了 8 毫秒)[分配失败]。
内存分配器,使用:1089495040,可用:2123341824
新空间,已用:1012304,可用:3182000               
旧指针,已使用:627968088,可用:16484264,浪费:0
旧数据空间,已使用:316947304,可用:53656,浪费:0
代码空间,已用:6039008,可用:1100320,浪费:0
地图空间,已使用:10275280,可用:6366768,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2122276608
91645948 毫秒:Scavenge 969.8 (1039.0) -> 968.6 (1041.0) MB,9 毫秒(自上次 GC 以来的 35 步中增加了 188 毫秒)[分配失败]。
内存分配器,使用:1091592192,可用:2121244672
新空间,已用:1032320,可用:3161984
旧指针,已使用:628219008,可用:16233344,浪费:0
旧数据空间,已使用:318537928,可用:526904,浪费:0
代码空间,已用:6039264,可用:1100064,浪费:0
地图空间,已用:10276232,可用:6365816,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2120179456
91646093 毫秒:Scavenge 971.6 (1041.0) -> 970.5 (1042.0) MB,13 毫秒(自上次 GC 以来的 30 步中增加了 36 毫秒)[Runtime::PerformGC]。
内存分配器,使用:1092640768,可用:2120196096
新空间,已用:2044456,可用:6344152
旧指针,已使用:628437424,可用:16014928,浪费:0
旧数据空间,已使用:319366376,可用:730392,浪费:0
代码空间,已用:6039264,可用:1100064,浪费:0
地图空间,已用:10276232,可用:6365816,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已用:51413600,可用:2119130880
91646306 毫秒:Scavenge 976.5 (1042.0) -> 974.7 (1044.0) MB,1 / 14 毫秒(自上次 GC 以来的 67 步中增加了 114 毫秒)[分配失败]。
内存分配器,使用:1094737920,可用:2118098944
新空间,已用:2064112,可用:6324496
旧指针,已使用:630440024,可用:14012328,浪费:0
旧数据空间,已使用:321653384,可用:507256,浪费:0
代码空间,已用:6055936,可用:1083392,浪费:0
地图空间,已使用:10278192,可用:6363856,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已用:51413600,可用:2117033728
91646386 毫秒:Scavenge 980.6 (1044.0) -> 979.2 (1046.0) MB,12 毫秒(自上次 GC 以来 64 步中增加了 10 毫秒)[分配失败]。
内存分配器,使用:1096835072,可用:2116001792
新空间,已用:4127736,可用:12649480
旧指针,已使用:631182984,可用:13269368,浪费:0
旧数据空间,已使用:323586008,可用:638504,浪费:0
代码空间,已用:6055936,可用:1083392,浪费:0
地图空间,已使用:10278192,可用:6363856,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已用:51413600,可用:2114936576
由于推广率高,新空间有限:1 MB
91646810 ms: Mark-sweep 979.2 (1046.0) -> 973.2 (1049.0) MB, 1 / 422 ms (+ 2500 ms in 303 steps in since the beginning of marking, max step 0.122070 ms) [StackGuard GC request] [GC in old space requested ]。
内存分配器,使用:1099980800,可用:2112856064
新空间,已使用:192,可用:1048384
旧指针,已使用:636894816,可用:9621408,浪费:0
旧数据空间,已使用:325256448,可用:0,浪费:0
代码空间,已用:5860928,可用:1278400,浪费:0
地图空间,已使用:10257976,可用:6384072,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2111790848
91646825 毫秒:清除 974.2 (1049.0) -> 979.0 (1049.0) MB,7 毫秒 [分配失败]。
内存分配器,使用:1099980800,可用:2112856064
新空间,已用:257960,可用:790616
旧指针,已使用:635948464,可用:10567760,浪费:0
旧数据空间,已使用:325256448,可用:0,浪费:0
代码空间,已用:5873440,可用:1265888,浪费:0
地图空间,已使用:10258536,可用:6383512,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2111790848
91646834 毫秒:清除 979.7 (1049.0) -> 980.0 (1049.0) MB,2 毫秒 [分配失败]。
内存分配器,使用:1099980800,可用:2112856064
新空间,已用:257968,可用:790608
旧指针,已使用:635671408,可用:10844816,浪费:0
旧数据空间,已使用:325256448,可用:0,浪费:0
代码空间,已用:5873440,可用:1265888,浪费:0
地图空间,已使用:10258536,可用:6383512,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2111790848
91646842 毫秒:清除 980.7 (1049.0) -> 980.6 (1049.0) MB,2 毫秒 [分配失败]。
内存分配器,使用:1099980800,可用:2112856064
新空间,已用:257960,可用:790616
旧指针,已使用:635493872,可用:11022352,浪费:0
旧数据空间,已使用:325256448,可用:0,浪费:0
代码空间,已用:5873440,可用:1265888,浪费:0
地图空间,已使用:10258536,可用:6383512,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2111790848
91646849 毫秒:清除 981.3 (1049.0) -> 981.2 (1049.0) MB,1 毫秒 [分配失败]。
内存分配器,使用:1099980800,可用:2112856064
新空间,已用:257968,可用:790608
旧指针,已使用:635981640,可用:10534584,浪费:0
旧数据空间,已使用:325256448,可用:0,浪费:0
代码空间,已用:5873440,可用:1265888,浪费:0
地图空间,已使用:10258536,可用:6383512,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2111790848
91646863 毫秒:清除 981.9 (1049.0) -> 981.6 (1051.0) MB,1 毫秒 [分配失败]。
内存分配器,使用:1102077952,可用:2110758912
新空间,已用:257960,可用:790616
旧指针,已使用:637013288,可用:10534872,浪费:0
旧数据空间,已使用:326288384,可用:0,浪费:0
代码空间,已用:5873440,可用:1265888,浪费:0
地图空间,已使用:10258536,可用:6383512,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2109693696
91651639 毫秒:标记扫描 981.6 (1051.0) -> 924.7 (1051.0) MB,1 / 4775 毫秒 [最后的 gc]。
内存分配器,使用:1102077952,可用:2110758912
新空间,已用:96,可用:1048480
旧指针,已使用:626794192,可用:20753968,浪费:0
旧数据空间,已使用:275760200,可用:50528184,浪费:0
代码空间,已用:6182208,可用:957120,浪费:0
地图空间,已使用:10257808,可用:6384240,浪费:0
单元空间,已用:176192,可用:954048,浪费:0
大对象空间,已使用:51413600,可用:2109693696
91663655 毫秒:标记扫描 924.7 (1051.0) -> 924.7 (1050.0) MB,1 / 12015 毫秒 [最后的 gc]。
内存分配器,使用:1101029376,可用:2111807488
新空间,已用:0,可用:1048576
旧指针,已使用:626169464,可用:21378696,浪费:0
旧数据空间,已使用:275759960,可用:49496488,浪费:0
代码空间,已用:5850624,可用:1288704,浪费:0
地图空间,已使用:10257808,可用:6384240,浪费:                 


我可以做任何调整来更好地配置 v8 的内存管理吗?关于这里有什么帮助的任何想法?

4

1 回答 1

25

我认为这是V8的限制。它在 64 位机器上使用的 RAM 不超过 1.7 GB。来自常见问题解答

目前,默认情况下,v8 在 32 位系统上的内存限制为 512mb,在 64 位系统上为 1gb。可以通过将 --max-old-space-size 设置为最大 ~1gb(32 位)和 ~1.7gb(64 位)来提高限制,但建议您将单个进程拆分为多个 worker如果你达到内存限制。

因此,在此之后,您将达到最大内存限制,并且由于垃圾收集而导致的 10 秒暂停是一个大问题。您应该考虑定期/在空闲时运行垃圾收集器,以避免达到限制并面临长时间的延迟。

您可以传递以帮助解决这种情况的参数是:(查看此博客

  • --nouse-idle-notification这可以防止不断运行 GC 并且
  • --expose-gc这将允许您从代码中运行 GC。

最重要的是调试您的代码以消除内存泄漏。使用这些包在您的代码中找到它们:

于 2013-05-16T15:41:59.123 回答