我得到的反馈是,此节点功能在获取文件的行数方面存在性能问题,但无法确定详细信息。
function countFileLines(filePath){
return new Promise((resolve, reject) => {
let lineCount = 0;
fs.createReadStream(filePath)
.on("data", (buffer) => {
buffer.forEach((chunk) => {
if (chunk === 10) lineCount++;
});
}).on("end", () => {
resolve(lineCount);
}).on("error", reject);
});
};
在Node中获取文件的行数是否有更高效的方法?
答案 0 :(得分:3)
function countFileLines(filePath){
return new Promise((resolve, reject) => {
let lineCount = 0;
let i = 0;
fs.createReadStream(filePath)
.on("data", (buffer) => {
for (i = 0; i < buffer.length; ++i) {
if (buffer[i] == 10) lineCount++;
}
}).on("end", () => {
resolve(lineCount);
}).on("error", reject);
});
};
进行比较:
原文:node index.js 2.38s user 0.29s system 98% cpu 2.713 total
修改:node index2.js 0.18s user 0.04s system 96% cpu 0.225 total
答案 1 :(得分:1)
我只能推测,但是buffer.forEach
调用一个函数并对每个字节进行比较可能是个问题。考虑使用indexOf让VM为您找到换行符:
function countFileLines(filePath){
return new Promise((resolve, reject) => {
let lineCount = 0;
fs.createReadStream(filePath)
.on("data", (buffer) => {
let idx = -1;
lineCount--; // Because the loop will run once for idx=-1
do {
idx = buffer.indexOf(10, idx+1);
lineCount++;
} while (idx !== -1);
}).on("end", () => {
resolve(lineCount);
}).on("error", reject);
});
};
此解决方案的作用是使用.indexOf
找到第一个换行符的位置。它递增lineCount
,然后找到下一个位置。 .indexOf
的第二个参数告诉我们从哪里开始寻找换行符。这样我们就跳过缓冲区的大块。对于每个换行,while循环将运行一次,加上一个。
我们让Node运行时搜索我们,这是在较低级别实现的,应该更快。
在我的系统上,这大约是在大文件(111 MB)上缓冲区长度上运行for
循环的速度的两倍。