Node.js readStream用于大文件的结尾

时间:2014-06-20 22:27:52

标签: node.js logging stream filestream large-files

我想偶尔在电子邮件通知中发送我的大型日志文件的最后2kB(> 100MB)。现在,我正在尝试以下方法:

var endLogBytes = fs.statSync(logFilePath).size;
var endOfLogfile = fs.createReadStream(logFilePath, {start: endLogBytes-2000, end: endLogBytes - 1, autoClose: true, encoding: 'utf8'});
endOfLogfile.on('data', function(chunk) {
    sendEmailFunction(chunk);
}

由于我刚刚重新启动,我的日志文件只有大约2MB,但随着它们变大,我想知道:

1)是否需要很长时间才能读出数据(节点是否会遍历整个文件,直到它到达我想要的字节或节点是否跳转到我想要的字节?)

2)消耗了多少内存?

3)什么时候内存空间被释放?如何释放内存空间?

1 个答案:

答案 0 :(得分:2)

在这种情况下你不应该使用ReadStream;因为它是一个流,它必须(我想)在所有前置数据到达最后两千字节之前研磨它。 所以我只使用打开文件的描述符fs.open然后fs.read。像那样:

fs.open(logFilePath, 'r', function(e, fd) {
  if (e)
    throw e; //or do whatever you usually doing in such kind of situations
  var endOfLogfile = new Buffer(2048);
  fs.read(fd, endOfLogFile, endLogBytes-2048, 2048, null, function(e, bytesRead, data) {
    if (e)
      throw e;
    //don't forget to data.toString('ascii|utf8|you_name_it')
    sendEmailFunction(data.toString('ascii'));
  });
});

更新: 似乎当前的ReadStream智能实现足以只读取所需的数据量。见:https://github.com/joyent/node/blob/v0.10.29/lib/fs.js#L1550。它使用了引擎盖下的fs.open和fs.read。所以你可以毫无顾虑地使用ReadStream。 无论如何我会用fs打开/读取,因为它更明确,C-way,更好的风格等等。

关于记忆并释放它。您将需要至少2Mb的内存用于数据缓冲区+一些开销。我不认为有一些方法可以确定它将花费多少开销。只需使用您的目标操作系统和节点版本进行测试。您可以使用此模块进行性能分析:https://www.npmjs.org/package/webkit-devtools-agent

当你不使用数据缓冲区时,内存将被释放,GC将决定这是收集垃圾的好时机。 GC是不确定的(即不可预测的)。你不应该试图预测它的行为或强迫它以任何方式进行垃圾收集。