Node.js vm 内存泄漏,不知道为啥,快疯了
发布于 6 年前 作者 zhaochy1990 4281 次浏览 来自 问答

测试代码如下

function memoryUsage() {
  const mem = process.memoryUsage();
  console.log(`rss: ${mem.rss / 1024 / 1024}M, heapTotal: ${mem.heapTotal / 1024 / 1024}M, heapUsed: ${mem.heapUsed / 1024 / 1024}M`);
}

app.post('/vm/test', async (req, res) => {
  try {
    let vm = require('vm');
    const code = `
    ${new Array(100000).join('/')}
    `;
    let script = vm.createScript(code);
    let vmCtx = vm.createContext();

    script.runInContext(vmCtx);
    script = null;
    vm = null;
    vmCtx = null;
    global.gc();
	memoryUsage(); // 打印出来当前的heap状态
    res.send('ok');
  } catch (e) {
    console.log(e.message);
    res.status(500).send(e.message);
  }
});

然后就发现内存抽风了 image.png

求大神帮忙看看什么问题,在线等!

4 回复

其实没有泄漏,不要用 --inspect 启动这个应用,inspector attach 到 node 进程后,确实会有一些 global handles 诡异的没法释放 你可以试下正常用 node 启动进程,然后比如 10s 打印下当前的堆内存就知道了

function memoryUsage() {
  const mem = process.memoryUsage();
  console.log(`rss: ${mem.rss / 1024 / 1024}M, heapTotal: ${mem.heapTotal / 1024 / 1024}M, heapUsed: ${mem.heapUsed / 1024 / 1024}M`);
}

setInterval(memoryUsage, 10 * 1000);

这样子可以看到内存是可以正常回收的

@hyj1991

我的测试脚本如下,然后每次invoke的时候都用你的这个函数把堆打印出来,测试了一下,依然有泄漏啊…

const axios = require('axios');

async function main() {
  try {
    let i = 1;
    while( i<100000 ) {
      await axios.post('http://localhost:3000/vm/test');  // 这个请求会执行我一开始的那个 app.post
    }
    console.log('done');
  } catch (e) {
    console.log(e.message);
  }
}

main();

@zhaochy1990 我之前用axios在node环境下使用的时候也遇到过,不过当时我用了CancelToken这个特性,这个特性是有内存泄漏的。后面去掉了就好了。

试了一下没碰到泄露:

function memoryUsage() {
  const mem = process.memoryUsage();
  console.log(`rss: ${mem.rss / 1024 / 1024}M,\theapTotal: ${mem.heapTotal / 1024 / 1024}M,\theapUsed: ${mem.heapUsed / 1024 / 1024}M`);
}

function test () {
    let vm = require('vm');
    const code = `${new Array(100000).join('/')}`;
    let script = vm.createScript(code);
    let vmCtx = vm.createContext();

    script.runInContext(vmCtx);
    script = null;
    vm = null;
    vmCtx = null;
    memoryUsage();
}

setInterval(test, 0);
回到顶部