如何确定给定内存限制的节点--max_old_space_size?

时间:2017-02-13 19:53:40

标签: node.js v8

我们在Docker容器中运行具有1GB,2GB或4GB硬内存容量的Node进程。每个容器通常只运行一个Node进程(加上一个小的shell脚本包装器)。让我们假设为了这个问题的目的,节点过程永远不会要求更多的过程。

对于我们较大的容器,如果我们自己没有设置--max_old_space_size,那么在我们使用的Node版本中(在64位计算机上)defaults to 1400MB。 (这将在更高版本的Node中change to 2048MB。)

理想情况下,我们希望我们的Node进程尽可能多地使用容器,而不会过度耗尽内存。问题是 - 我们应该使用多少号码?我的理解是这个特定的标志调整了Node使用的最大内存池之一的大小,但它不是唯一的池 - 例如,堆中有一个“非旧”部分,有栈,等等。我应该在设置此标志时减去容器的大小,以便远离cgroup内存限制,但仍然最大限度地利用此容器中允许的内存量?

我注意到,在定义kMaxOldSpaceSizeHugeMemoryDe​​vice的同一个地方,看起来默认的“max semi space”是16MB,默认的“max executable size”是512MB。所以我怀疑这意味着在确定此标志的值时,我应该从容器的内存限制中减去至少528。但是,当然还有Node使用内存的其他方式吗?

(更具体地说,我们是一个托管服务,向我们的用户销售特定尺寸的容器,其中大部分用于Node流程。我们希望能够告诉我们的客户要设置什么标志所以他们既没有被我们的限制所杀,也没有向我们支付Node的配置不允许他们实际使用的容量。)

1 个答案:

答案 0 :(得分:2)

不幸的是,这个问题没有特别令人满意的答案。

您发现的常量控制着垃圾收集堆的大小,但正如您已经猜到的那样,有很多方法可以消耗不属于该堆的内存:< / p>

  • 例如,大字符串和大型TypedArrays通常由嵌入器(即节点及其模块,而不是V8本身)以及GC的堆外部管理。
  • 节点模块通常可以消耗他们想要的任何内存。大概你不想限制你的客户可以运行哪些模块,但这意味着你也无法预测这些模块需要多少内存。
  • V8还使用GC堆外的临时内存进行解析和编译。数字取决于正在运行的代码,从几千字节到几千兆字节或更多(例如对于巨大的asm.js代码库),一切皆有可能。这些是相对短暂的内存消耗峰值,所以一方面你可能不想限制长期堆内存来解释它们,但另一方面,这意味着它们可以让你的进程运行到系统限制。