2013-11-23 15 views
1

我想要做什么应该看起来很简单:采用文件名为X的文件,并创建一个gzipped版本为“X.gz”。的NodeJS的zlib的模块不拿出一个方便zlib.gzip(INFILE,OUTFILE),所以我想我会用的输入流,输出流和zlib的但gzipper,然后通过管道它们:gzipping与nodejs流文件导致内存泄漏

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文件而不打扰流和管道?我试着用google搜索“node.js gzip文件”,但它只是指向API文档的链接,以及关于gzipping流和缓冲区的堆栈溢出问题,而不是如何只是gzip文件。

回答

2

我觉得你需要正确的unpipeclose这个流。只需removeAllListeners()可能不足以清理干净。由于流可能正在等待更多数据(并因此不必要地在内存中保持活跃状态​​)。

另外,您还没有关闭输出流,而且我会听输入流的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); 

没有带测试此寿,因为我没有记忆曲线工具附近现在。

+0

好点,但如果调用close(),removealllisteneres和null赋值就不再需要了。我最终选择了直接in.pipe(out)并重新指定每个周期,然后使用less pipe -y readfile/gzip/writefile/unlink来对最终完成的文件进行gzip压缩,但仍得到满意答案。 –