swap、堆上限和构建内存墙

工程化与部署

接着上一篇,把三件事的关系说清楚,因为我一开始把两个概念混了。

V8 的堆上限是"这个 JS 进程最多能申请多少内存"。它跟物理内存无关,是一个软限制,默认按机器内存推算。Node 在 1.9G 的机器上给的大约是 2G 不到,但构建过程中实际峰值需要更多,于是先撞到这个软限制,报 heap out of memory。抬它是告诉 V8:"允许你继续要。"

swap 是"要了之后真给得出"。没有 swap,抬高的上限就是空头支票,进程会一路申请到物理内存加缓存全满,然后被内核 OOM killer 挑中杀掉——表现是没有任何 JS 报错,进程直接消失。

所以两个必须一起调。只抬上限,撞墙的方式从 V8 报错变成被内核杀;只加 swap,V8 还是会在自己的上限前退出。

调完还要看它到底用了多少。构建时另开一个终端:

watch -n 2 free -h

Swap used 那一列如果一路涨到 1.5G,说明构建确实吃到了 swap,慢是必然的。这时该考虑的不是继续加数字,而是换地方构建。

几条经验性的判断:

构建慢和构建失败是两回事,别用加内存解决慢。
容器里的内存限制(mem_limit)如果比堆上限低,先撞的是容器那层,报错也很含糊。
最省心的解法是别让生产机参与构建。我这台 1.9G 的机器后来只负责 pull 和跑,构建交给 CI,一次配置换来以后所有发版都不再关心内存。

相关阅读