使用nodejs流gzipping文件会导致内存泄漏

时间:2013-11-23 22:27:20

标签: node.js stream zlib

我正在尝试做看似非常简单的事情:使用文件名为X的文件,并创建一个gzip压缩版本为“X.gz”。 Nodejs的zlib模块没有方便的zlib.gzip(infile,outfile),所以我想我会使用输入流,输出流和zlib gzipper,然后管道它们:

var zlib = require("zlib"),
    zipper = zlib.createGzip(),
    fs = require("fs");

var tryThing = function(logfile) {
  var input = fs.createReadStream(logfile, {autoClose: true}),
       output = fs.createWriteStream(logfile + ".gz");

  input.pipe(zipper).pipe(output);

  output.on("end", function() {
    // delete original file, it is no longer needed
    fs.unlink(logfile);

    // clear listeners
    zipper.removeAllListeners();
    input.removeAllListeners();
  });
}

然而,每次运行此函数时,Node.js的内存占用量增加约100kb。我忘了告诉他们他们应该再次自杀,因为他们不再需要了吗?

或者,有没有办法只是gzip文件而不打扰流和管道?我试着用谷歌搜索“node.js gzip一个文件”,但它只是链接到API文档,而且是关于gzipping流和缓冲区的堆栈溢出问题,而不是如何只是gzip文件。

1 个答案:

答案 0 :(得分:2)

我认为您需要正确unpipeclose信息流。简单地removeAllListeners()可能不足以清理事物。因为流可能正在等待更多数据(因此不必要地在内存中保持活跃。)

另外你也没有关闭输出流和IMO我会在输入流的end而不是输出上听。

// cleanup
input.once('end', function() {
  zipper.removeAllListeners();
  zipper.close();
  zipper = null;
  input.removeAllListeners();
  input.close();
  input = null;
  output.removeAllListeners();
  output.close();
  output = null;
});

此外,我不认为从zlib.createGzip()返回的流可以在结束时共享。您应该在tryThing的每次迭代中创建一个新的:

var input = fs.createReadStream(logfile, {autoClose: true}),
  output = fs.createWriteStream(logfile + ".gz")
  zipper = zlib.createGzip(); 

input.pipe(zipper).pipe(output);

我没有测试过这个,因为我现在附近没有内存配置文件工具。