我昨天意识到Node.js的大多数日志库似乎都使用阻塞/同步调用.日志记录通常是I / O操作,对于Node.js,我们应该尽可能使用非阻塞/异步I / O. console.log(process.stdout.write)自Node.js 0.6,TMK以来一直是
console.log(process.stdout.write)自Node.js 0.6,TMK以来一直是同步操作
在我看来,对于执行大量日志记录语句的服务器来说,使用阻塞I / O可能会造成很大的性能损失.
我在Redis,fs,Bunyan和Winston上运行了“日志记录”语句,我在Macbook Pro上得到了这些结果:
redis: 16ms
fs-write-stream: 90ms
bunyan: 414ms
winston: 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将日志记录请求发送到某处的日志服务器,这将处理队列.
我刚刚意识到我在基准测试中犯了一个错误 – 我需要将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'); });
在进行这种改变之后,Redis实际上比fs.createWriteStream慢得多,但仍然是Bunyan和Winston的两倍,可能是因为它没有在输入上调用JSON.stringify.
最底层的是,fs.createWriteStream比Bunyan或Winston更快……但我不确定这对于非常小的I / O操作是否重要.