V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kernel
V2EX  ›  Node.js

搞定了 NodeJS 程序占内存多的问题

  •  
  •   kernel · 2019-01-04 09:42:40 +08:00 · 14169 次点击
    这是一个创建于 2182 天前的主题,其中的信息可能已经有所发展或是发生改变。
    去年转到 node 后发现真香,所有的微服务全都用 node 写了,然后马上发现了一个问题,之前 python 写的程序第 1 天和每 1000 天运行的内存都是一样的,而 node 程序会比较快地增长,直到 boom。

    后来发现是因为 node 默认内存限制 1.7G ,而我的小机全是 1G - 2G 的,内存不足。
    Google 了一翻,加上命令行选项

    --max_old_space_size=600 --max_semi_space_size=8

    发现有很大缓解,boom 的次数很少了,但是有另一个问题,就是运行二天后 node 内存就占了 600 - 800M 左右,但是没 Google 到别的解法,就这样将就了一年。

    前几天翻 github 时发现另一个解法,在前面选项的基础上再替换默认内存分配器,用 jemalloc。

    debian 上是

    apt install libjemalloc-dev

    然后运行 node 前
    export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1

    我是用 systemd 的,service 文件里加一行
    Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1
    就行。

    然后运行了三天,以前会占用 700M 内存的程序目前稳定在 120M 了,和以前 python 类似。
    第 1 条附言  ·  2019-01-04 10:29:25 +08:00
    对了,之前还试过 gc_interval 和 optimize_for_size 这二选项,没卵用
    14 条回复    2020-03-24 10:55:14 +08:00
    yimity
        1
    yimity  
       2019-01-04 10:09:25 +08:00
    这个是为啥呢?
    zy445566
        2
    zy445566  
       2019-01-04 10:19:46 +08:00
    你的 node 是什么版本的,是否使用了 buffer,之前听说 node 修复了一个 buffer 导致内存泄露的 BUG
    kernel
        3
    kernel  
    OP
       2019-01-04 10:24:06 +08:00
    @zy445566 不是,各种版本都一样,目前混用 9 lts 和 10lts
    kernel
        4
    kernel  
    OP
       2019-01-04 10:28:21 +08:00
    @yimity 感觉就是不会主动释放空闲内存回 OS,会慢慢占满你指定的 max_old_space_size。
    zy445566
        5
    zy445566  
       2019-01-04 10:29:35 +08:00
    真的很神奇,但你这个是典型的内存泄露,居然可以通过改 jemalloc 化解,真想知道原因
    kernel
        6
    kernel  
    OP
       2019-01-04 10:34:15 +08:00
    @zy445566 不是内存泄露,我写了好多 node 微服务,全这样,这特么不是我的锅吧
    (因为有一个还特简单,不到 100 行,就是转一下图片格式)

    另外你 google 一下,小内存机子运行 node 全是这问题, 参考
    https://github.com/damianmr/heroku-node-settings
    libook
        7
    libook  
       2019-01-08 11:49:31 +08:00
    用了五年 Node 了,只有最开始的两年遇到过 Node 内存泄露的问题,当时是定时重启,后来到了 Node6 好像就没有遇到过内存泄漏问题了,阿里云几十台 1 核 2G 的机器,分布式部署一个程序稳定运行数周,内存正常。。。

    如果你用 Debian 的目前稳定版的话,我看到 nodejs 包依赖了 libc (其实就是 glibc ):
    https://packages.debian.org/stretch/nodejs

    或者你用 n、nvm 之类的安装 Node,不清楚是不是会直接用系统内预装的 glibc ?

    所以会不会是你装的多数版本的 Node 都是共用的某一个版本的 glibc 提供的内存分配器,而这个版本内存分配器有内存泄漏问题,所以导致不管哪个版本的 Node 都有这个问题。。。实际上你的试验只控制了内存分配器这一个变数,所以基本能得出这个结论。

    所以如果有时间可以尝试一下升级系统内的内存分配器动态链接库的版本,看看是不是也能解决这个问题?或者看看默认内存分配器的 issue 或 changelog 是否有提到相关内存泄露问题。
    kernel
        8
    kernel  
    OP
       2019-01-08 12:20:17 +08:00
    @libook 之前加了 max_old_space_size 后内存占用大,但是到那个限制后就不再增加了,程序也不崩,应该不是内存泄漏问题。jemalloc 看一些文章说明它是有缓解内存碎片减少 RSS 的作用。
    zy445566
        9
    zy445566  
       2019-01-10 17:48:04 +08:00
    @kernel
    巧了,三天前我也是这么猜测的
    https://cnodejs.org/topic/5c300bf15bf06c5e7e3f17d7#5c330ce13898674067a7c19a
    说不定真可以试一下升级内置的内存动态分配器
    zy445566
        10
    zy445566  
       2019-01-10 17:54:10 +08:00
    @kernel
    老哥,说真的,真希望你能研究一下,然后公开一下研究成果。
    我手上没你的代码资源和机子的环境,我这边死都复现不了,纠结死了。
    haohello
        11
    haohello  
       2019-01-16 15:13:07 +08:00
    @kernel 你可以看看朴灵写的《深入浅出 nodejs 》,这本书虽然出了都好几年了,但是原理性的内容却是市面上唯一讲到的,里面有专门一节讲述 node 内存的一章,你所提到的内存限制其实都是 v8 对于 js 对象的大小限制,可以多用用 buffer, stream 这些。
    zzwwjjdj319
        12
    zzwwjjdj319  
       2019-01-31 14:14:18 +08:00
    为什么我的一直都是 70 多 MB,没出现过你说的几百 M 的
    maxsky
        13
    maxsky  
       2019-05-17 16:24:24 +08:00
    我也一直 600+M,CentOS 7 和 macOS 都是,分别 Node 10 与 12 版本,两个系统都试了下启动 Node 前 export LD_PRELOAD 并指定 jemalloc,内存依旧...会不会是 Node 版本原因
    toma77
        14
    toma77  
       2020-03-24 10:55:14 +08:00
    @maxsky
    我跟你一样的情况,你问你后面怎么解决的呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3104 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:16 · PVG 21:16 · LAX 05:16 · JFK 08:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.