Node.js使用jemalloc内存分配器显著减少内存使用

前言

Node.js 默认使用的是 ptmalloc(glibc) 内存分配器,而:

在服务端领域「不会选择默认的 malloc」是一个常识。( 来源

ptmalloc 的分配效率较低( 来源 ),对于 长时间、多核 / 多线程 运行的程序( 来源 ),特别适合使用 jemalloc 分配器,使用 jemalloc 分配内存可以更好的处理 内存碎片 问题( 来源 )。

jemalloc 并不总是最优的( 来源 ),但十分适合服务端 Node.js 程序使用。

正文

Linux
 # install
  sudo apt-get update
  sudo apt-get install -y libjemalloc-dev
  
  # run
  # 启动的时候添加 jemalloc 分配器,`LD_PRELOAD` 的格式是以空格为分割。
  LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so $LD_PRELOAD" node index.js

jemalloc 写入 ld.so.preload 可以让所有写入之后运行的进程默认使用 jemalloc 分配器,一般没必要,除非你有会启动多个进程的场景:

echo "/usr/lib/x86_64-linux-gnu/libjemalloc.so" >> /etc/ld.so.preload

检验对应的 node 进程是否正确使用了 jemalloc

  # 使用 top 等工具找到对应 node 进程的 pid 再查询即可
  sudo cat /proc/<PID OF NODEJS>/smaps | grep jemalloc
macOS
  # install
  brew install jemalloc

  # run
  # 在具体使用时 `${version}` 版本号的部分换成你自己安装的即可
  DYLD_INSERT_LIBRARIES=/usr/local/Cellar/jemalloc/5.3.0/lib/libjemalloc.dylib node index.js
  #                                                ^ ${version}
检验脚本

运行以下脚本可以测试 jemalloc 是否生效,默认情况下会使用多达 4 G 内存,若使用 jemalloc ,则使用内存会大大减少至几十 M 。

注:不要在内存不足 8 G 的服务器上运行,剩余内存不够会直接宕机。

// index.js

const bs = 4 * 1024 * 1024; // 4 MiB
const retained = [];
let i = 0, flag = false;

function tick() {
   
  i++;
  if (i % 1000 === 0) {
   
    console.log(`RSS [${
     i}]: ${
     process.memoryUsage().rss / 1024 / 1024} MiB`);
  }
  retained.push(Buffer.allocUnsafe(bs));
  if (i === 5000) {
   
    console.log('Clearing retained and enabling alloc');
    retained.length = 0;
    flag = true;
  }
  if (flag) Buffer.alloc(bs); // Buffer.alloc(bs - 10) seems to be fine here
  if (i < 10000) setImmediate(tick);
}

tick();

例子

个人例子:使用 jemalloc 后,在我的服务端程序上原持续占用 900 M 内存的程序,现会在 200 M900 M 之间波动,可以看到回收效率显著提高,在调用需求下降时(如半夜),内存使用大幅减少:

经典例子:npmmirror 使用 jemalloc 大幅减少占用内存。( 来源

总结

对于 长时间、多进程 的 Node.js 服务端程序,我们可以切换至 jemalloc 内存分配器提高内存回收效率,特别对于易产生内存碎片(如大量 JSON 序列化)的场景,格外有效。

实践中,修订容器脚本,在镜像构建时运行对应的命令即可。

相关推荐

  1. 【Linux上使用jeprof和jemalloc分析内存泄漏的方法】

    2024-01-02 07:46:01       45 阅读
  2. python使用迭代生成器yield减少内存占用的方法

    2024-01-02 07:46:01       39 阅读
  3. Linux - 内存 - memblock 分配器

    2024-01-02 07:46:01       62 阅读
  4. SqlServer内存使用情况

    2024-01-02 07:46:01       70 阅读
  5. MongoDB管理内存使用

    2024-01-02 07:46:01       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-02 07:46:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-02 07:46:01       101 阅读
  3. 在Django里面运行非项目文件

    2024-01-02 07:46:01       82 阅读
  4. Python语言-面向对象

    2024-01-02 07:46:01       91 阅读

热门阅读

  1. 数据结构OJ实验13-动态查找

    2024-01-02 07:46:01       40 阅读
  2. PDF模板填充,基于IText5(改进版)

    2024-01-02 07:46:01       55 阅读
  3. Avalonia框架下实现热更新

    2024-01-02 07:46:01       54 阅读
  4. MYSLQ——InonoDB的事务

    2024-01-02 07:46:01       52 阅读
  5. 下界通配符(? super Type)

    2024-01-02 07:46:01       68 阅读
  6. Python中的os模块中的常用方法

    2024-01-02 07:46:01       44 阅读
  7. Zynq中spi、iic等协议配置器件

    2024-01-02 07:46:01       57 阅读
  8. 循环展开与Duff Device

    2024-01-02 07:46:01       67 阅读
  9. 阿里云服务器节省计划价格便宜_成本优化全解析

    2024-01-02 07:46:01       62 阅读
  10. OpenSSL provider

    2024-01-02 07:46:01       64 阅读