2015-11-03 39 views
4

我昨天意識到,大多數Node.js的日誌庫似乎都使用阻塞/同步調用。日誌記錄通常是一個I/O操作,使用Node.js,我們應該在任何可能的地方使用非阻塞/異步I/O。基準測試Node.js日誌記錄系統 - 我是否遺漏了一些相關信息?

console.log(process.stdout.write)一直以來的Node.js 0.6同步操作,TMK

我突然想到,對於做記錄語句的很多服務器,用於阻塞I/O這可能是一個很大的性能損失。

我跑了Redis的,FS,班揚和溫斯頓 「日誌」 的語句,我得到在MacBook Pro上的結果:

的Redis:16ms的

FS-寫流:90毫秒

本仁: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'); 


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

我是對的東西還是我有什麼不對?

理想情況下,Node.js服務器看起來好像使用Redis將日誌記錄請求發送到某處的日誌服務器,這將處理隊列。

+0

我也將它運行到系統日誌到/ dev/null並且得到了「syslog-time:54ms」,當我將bunyan記錄到/ dev/null並將winston記錄到/ dev/null時我得到了相同的結果 –

回答

0

我才意識到我在基準犯了一個錯誤 - 我需要包裝Redis的呼叫在像這樣(「準備好」)回調:做出這樣的轉變後

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'); 

}); 

,Redis的實際上是多比fs.createWriteStream慢,但仍然是Bunyan和Winston的兩倍,可能是因爲它沒有在輸入中調用JSON.stringify。底層石灰是fs.createWriteStream比Bunyan或Winston更快......但我不確定它是否對於非常小的I/O操作非常重要。

+1

這聽起來很奇怪。嘗試連續運行整組測試多個時間,然後計算每個記錄器的中位數 – matus

+0

嘗試它,在準備好處理程序中將新代碼複製到原始位置,並且您應該看到相同的結果 –

+0

難道你不知道嗎?認爲你正在使用的流的類型也起主要作用,因爲文件IO可能導致更高的開銷,爲什麼'bunyan'和'winston'需要更多時間。 – JohnTheBeloved