以下是NodeJS代码(同步版本)的示例:
var fs = require('fs');
var path = './parseLogFiles/reports';
var counter = 0;
var totalFileSize = 0;
var fileName;
var fullPath;
function toMb (byteVal) {
return (byteVal / 1048576).toFixed(2);
}
var filesList = fs.readdirSync(path);
console.log('Memory usage before files read:', toMb(process.memoryUsage()['heapUsed']) + ' MB');
for (var i = 0, len = filesList.length; i < len; i++) {
fileName = filesList[i];
if (fileName) {
fullPath = path + '/' + fileName;
totalFileSize += fs.statSync(fullPath)['size'];
try {
fs.readFileSync(fullPath, {encoding: 'utf8'});
} catch(err){
console.log('err: ', err);
}
}
}
console.log('Memory usage after files read:', toMb(process.memoryUsage()['heapUsed']) + ' MB');
console.log('Total files size:', toMb(totalFileSize) + ' MB');
我得到了以下结果:
文件读取前的内存使用情况:22.45 MB
读取文件后的内存使用情况:23.31 MB
文件总大小:258.19 MB
这是异步版本:
...
for (var i = 0, len = filesList.length; i < len; i++) {
fileName = filesList[i];
if (fileName) {
fullPath = path + '/' + fileName;
(function(fullPath){
fs.stat(fullPath, function(err, stat){
totalFileSize += stat['size'];
fs.readFile(fullPath, {encoding: 'utf8'}, function(){
if (++counter === len) {
console.log('Memory usage after files read:', toMb(process.memoryUsage()['heapUsed']) + ' MB');
console.log('Total files size:', toMb(totalFileSize) + ' MB');
}
});
});
})(fullPath);
}
}
我得到了以下结果:
文件读取前的内存使用情况:22.45 MB
读取文件后的内存使用情况:437.88 MB
文件总大小:258.19 MB
为什么会发生(23.31 MB vs 437.88 MB)?
答案 0 :(得分:2)
在同步版本中,数据会被垃圾收集,因为您没有将返回值分配给任何内容。在异步文件中,最终文件不允许被垃圾收集,因为它可以通过arguments
访问,即使您没有设置显式参数。
为了证明这一点,我在一个文件上设置了一个简单的测试。我在基本版本中得到了与你类似的结果(尽管我必须在每次内存使用检查之前强制使用gc)。但是,如果我只存储readFileSync
返回的数据,那么该版本使用的内存几乎与异步内存的数量完全相同。
如果您担心内存使用情况,则应使用fs.createReadStream。