【问题标题】:node.js readFile memory leaknode.js readFile 内存泄漏
【发布时间】:2014-06-27 11:29:29
【问题描述】:

我使用 node.js 每秒读取一张图片。这个想法是稍后将其推送到网络浏览器,使其成为一个简单的流。代码如下:

var fs      = require("fs");
var intervalTimerObj;

function startStream() {
    if(!intervalTimerObj) {
        intervalTimerObj = setInterval( updateStream  , 1000);
    }
}

function updateStream(){
    fs.readFile( __dirname + "/pic.jpg", function(err, image) {

    });
}

startStream();

运行上面的代码时,我的内存很快就被填满了,我似乎遇到了内存泄漏。 我加载的图像文件越大,填满的速度就越快。

我做错了什么?有没有办法“释放”图像变量?我试过把它归零。

【问题讨论】:

  • fs.readFile 回调中完成读取图像后,不要使用setInterval 更新流。最好先读一张图片,然后如果你真的需要 1000 毫秒的间隔来使用setTimeout 开始下一次阅读
  • 刚刚尝试使用 setTimeout 代替。仍然不断窃取我所有的记忆
  • 你为什么要每 1000 毫秒做一次呢?
  • 这个想法是每秒捕获一张图片,然后通过 socket.io 将其推送到网络浏览器

标签: javascript node.js file-io memory-leaks


【解决方案1】:

这是一个更好的方法。 setInterval() 不应在此处使用,因为它可能导致同时执行同一任务。请改用setTimeout()。这样做的理想位置是在readFile() 的回调中:

var fs            = require("fs");
var timeoutHandle = null;

function startTimeout() {
  stopTimeout();
  timeoutHandle = setTimeout(updateStream, 1000);
}

function stopTimeout() {
  clearTimeout(timeoutHandle);
}

function updateStream(){
    fs.readFile( __dirname + "/pic.jpg", function(err, image) {
      // ...

      startTimeout(); // Make sure this line is always executed
    });
}

startTimeout();

您还需要确保在处理完image 之后不要对其进行任何引用,否则V8 的垃圾收集器不会释放图像数据,从而导致内存泄漏。

【讨论】:

  • 我正在运行你的 startTimeout 函数,但内存仍然没有被释放。每次加载图像时,我的记忆都会增加。 startTimeout 对你有用吗?
  • 我已经对您的解决方案进行了长期测试,似乎内存使用量稳定在 ~40%(200mb) 内存使用量上。这是可以预料的吗?感谢您提供代码!
  • 是的,看起来很正常。在循环内处理大量数据时需要非常小心。很高兴为您提供帮助!
【解决方案2】:

试试这个

function startStream() {
    if(!intervalTimerObj) {
        intervalTimerObj = setTimeout( updateStream  , 1000);
    }
}

function updateStream(){
    fs.readFile( __dirname + "/pic.jpg", function(err, image) {
       //OK file is read
       //do yoyr stuff with it....
       // Now start next read
       startStream()
    });
}

startStream();

【讨论】:

  • 感谢您的代码。尽管如此,我的记忆还是一直在上升。我正在使用 top 命令(使用 linux)监视 ram,它永远不会崩溃。
  • 我猜你正在某个地方进入循环调用圈。检查您的代码,如果可能进行调试并想出一个更好的模式。如果新问题回来发布问题。这段代码就是这样的模式。 2 个函数互相调用
猜你喜欢
  • 2012-03-11
  • 2016-01-01
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 2015-11-04
相关资源
最近更新 更多