微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从node.js,更快,shell grep或fs.readFile?

我有一个长期运行的node.js进程,我需要扫描日志文件中的模式.我有至少两个明显的选择: spawn a grep process或使用 fs.read*读取文件并解析node.js中的缓冲区/流.我没有在intarwebs上找到两种方法的比较.我的问题有两个:

>哪个更快?
>为什么我更喜欢一种技术而不是另一种?

解决方法

这是我的nodejs实现,结果非常符合预期:
文件运行速度比分叉grep(文件长达2-3k短线)快,
文件运行速度较慢.文件越大,差异越大.
(也许正则表达式越复杂,差异越小 – 见
下面.)

我使用自己的qfgets快速
一次一行文件i / o;那里可能有更好的,我不知道.

我看到一个意外的异常,我没有调查:下面的时间
用于常量字符串regexp / foobar /.当我把它改成
/ [f] [o] [o] [b] [a] [r] /实际运用正则表达式引擎,grep减速
下降3倍,节点加速! grep的3倍减速可以重现
命令行.

filename = "/var/log/apache2/access.log";     // 2,540,034 lines,187MB
//filename = "/var/log/messages";             // 25,703 lines,2.5MB
//filename = "out";                           // 2000 lines,188K (head -2000 access.log)
//filename = "/etc/motd";                     // 7 lines,286B
regexp = /foobar/;

child_process = require('child_process');
qfgets = require('qfgets');

function grepWithFs( filename,regexp,done ) {
    fp = new qfgets(filename,"r");
    function loop() {
        for (i=0; i<40; i++) {
            line = fp.fgets();
            if (line && line.match(regexp)) process.stdout.write(line);
        }
        if (!fp.feof()) setImmediate(loop);
        else done();
    }
    loop();
}

function grepWithFork( filename,done ) {
    cmd = "egrep '" + regexp.toString().slice(1,-1) + "' " + filename;
    child_process.exec(cmd,{maxBuffer: 200000000},function(err,stdout,stderr) {
        process.stdout.write(stdout);
        done(err);
    });
}

考试:

function fptime() { t = process.hrtime(); return t[0] + t[1]*1e-9 }

t1 = fptime();
if (0) {
    grepWithFs(filename,function(){
        console.log("fs done",fptime() - t1);
    });
}
else {
    grepWithFork(filename,function(err){
        console.log("fork done",fptime() - t1);
    });
}

结果:

/**
results (all file contents memory resident,no disk I/O):
times in seconds,best run out of 5

/foobar/
             fork   fs
motd        .00876  .00358  0.41 x  7 lines
out         .00922  .00772  0.84 x  2000 lines
messages    .0101   .0335   3.32 x  25.7 k lines
access.log  .1367   1.032   7.55 x  2.54 m lines

/[f][o][o][b][a][r]/
access.log  .4244   .8348   1.97 x  2.54 m lines

**/

(上面的代码都是一个文件,我把它拆开以避免滚动条)

编辑:突出显示关键结果:

185MB,254万行,搜索RegExp / [f] [o] [o] [b] [a] [r] /:

grepWithFs

已过去:.83秒

grepWithFork

已过去:.42秒

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐