对Node.js日志记录系统进行基准测试-我是否缺少有关此方面的信息?

Ale*_*lls 5 logging redis node.js winston bunyan

昨天我意识到,Node.js的大多数日志记录库似乎都使用了阻塞/同步调用。日志记录通常是一个I / O操作,通过Node.js,我们应该尽可能使用非阻塞/异步I / O。

console.log (process.stdout.write)从Node.js 0.6,TMK开始一直是同步操作

在我看来,对于执行大量日志记录语句的服务器而言,对这些语句使用阻塞I / O可能会造成很大的性能损失。

我使用Redis,fs,Bunyan和Winston运行“记录”语句,然后在Macbook Pro上获得了以下结果:

redis:16毫秒

fs-write-stream:90ms

Bunyan:414ms

温斯顿:491ms

因此,似乎仅使用Redis客户端通过网络I / O发送消息是从Node.js事件循环中获取数据的最快方法。

测试如下:

    // fs
    var fs = require('fs');

    // redis
    var redis = require('redis');
    var client = redis.createClient();  //connect to local redis db

    // bunyan
    var bunyan = require('bunyan');

    var bunyanLogger = bunyan.createLogger({
        name: 'benchmark',
        streams: [
            {
                level: 'info',
                path: '../bunyan_log.txt'  // log ERROR and above to this file
            }
        ]
    });

    // winston
    var winston = require('winston');

    var winstonLogger = new (winston.Logger)({
        transports: [
            new (winston.transports.File)({ filename: '../winston_log.txt' })
        ]
    });


    ////////////////////////////////////////////////////////////////////////////

    console.time('redis-time');

    for (var i = 0; i < 12000; i++) {

        client.set('key' + i, 'value' + i + 'aegeggaiojigfeijoagreoiraegioagrijogerawijogerwijogerijoegwoijegwijoegwjio');

    }

    console.timeEnd('redis-time');

    ////////////////////////////////////////////////////////////////////


    console.time('fs-write-stream-time');

    var wstream = fs.createWriteStream('../fs_log.txt');

    for (var i = 0; i < 12000; i++) {

        wstream.write('key' + i + 'value' + i + 'aegeggaiojigfeijoagreoiraegioagrijogerawijogerwijogerijoegwoijegwijoegwjio' + '\n');

    }

    wstream.end();

    console.timeEnd('fs-write-stream-time');


    ///////////////////////////////////////////////////////////////


    console.time('bunyan-time');

    for (var i = 0; i < 12000; i++) {

        bunyanLogger.info('bunyan' + i);

    }

    console.timeEnd('bunyan-time');


    /////////////////////////////////////////////////////////////


    console.time('winston-time');

    for (var i = 0; i < 12000; i++) {

        winstonLogger.info('bunyan' + i);

    }

    console.timeEnd('winston-time');


////////////////////////////////////////////////////////////////
Run Code Online (Sandbox Code Playgroud)

我在做某事还是我做错了什么?

理想情况下,似乎在Node.js服务器上,您将使用Redis将日志记录请求发送到某个地方的日志记录服务器,该服务器将处理队列。

Ale*_*lls 0

我刚刚意识到我在基准测试中犯了一个错误 - 我需要将 Redis 调用包装在 on('ready') 回调中,如下所示:

client.on('ready',function(){

    console.time('redis-time');

    for (var i = 0; i < 12000; i++) {

        client.set('key' + i, 'value' + i + 'aegeggaiojigfeijoagreoiraegioagrijogerawijogerwijogerijoegwoijegwijoegwjio');

    }

    console.timeEnd('redis-time');

});
Run Code Online (Sandbox Code Playgroud)

进行此更改后,Redis 实际上比 慢得多fs.createWriteStream,但仍然是 Bunyan 和 Winston 的两倍左右,可能是因为它没有对输入调用 JSON.stringify。

最重要的是 fs.createWriteStream 比 Bunyan 或 Winston 快得多……但我不确定它对于非常小的 I/O 操作是否有那么重要。