Вчера я понял, что большинство библиотек ведения журналов для Node.js, похоже, используют блокирующие/синхронные вызовы. Ведение журнала обычно является операцией ввода-вывода, и с Node.js мы должны использовать неблокирующий/асинхронный ввод-вывод везде, где это возможно.
console.log
(process.stdout.write) является синхронной операцией, начиная с Node.js 0.6, TMK
Мне пришло в голову, что для серверов, которые выполняют множество операторов ведения журнала, использование блокирующего ввода-вывода для них может привести к значительному снижению производительности.
Я запустил операторы «логирования» с помощью Redis, fs, Bunyan и Winston и получил следующие результаты на Macbook Pro:
редис: 16 мс
fs-запись-поток: 90 мс
буньян: 414 мс
Уинстон: 491 мс
поэтому кажется, что просто использование клиента Redis для отправки сообщения через сетевой ввод-вывод — это самый быстрый способ получить данные из цикла событий 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 для отправки запросов ведения журнала куда-то на сервер ведения журнала, который будет обрабатывать очередь.