Как измерить время выполнения JavaScript-кода с обратными вызовами
У меня есть часть кода javascript, которую я выполняю с помощью интерпретатора node.js.
for(var i = 1; i < LIMIT; i++){
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
});
}
Я хочу знать, как измерить время, затрачиваемое этими операциями вставки db. Я мог бы вычислить разницу значений Date после и до этой части кода, но это было бы неправильно из-за асинхронного характера кода.
Ответы
Ответ 1
Используйте Node.js console.time()
и console.timeEnd()
:
var i;
console.time("dbsave");
for(i = 1; i < LIMIT; i++){
db.users.save({id : i, name : "MongoUser [" + i + "]"}, end);
}
end = function(err, saved) {
console.log(( err || !saved )?"Error":"Saved");
if(--i === 1){console.timeEnd("dbsave");}
};
Ответ 2
Существует метод, который предназначен для этого. Проверьте process.hrtime();.
Итак, я в основном помещаю это в начало моего приложения.
var start = process.hrtime();
var elapsed_time = function(note){
var precision = 3; // 3 decimal places
var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time
start = process.hrtime(); // reset the timer
}
Затем я использую его, чтобы посмотреть, как долго выполняются функции. Вот базовый пример, который печатает содержимое текстового файла с именем "output.txt":
var debug = true;
http.createServer(function(request, response) {
if(debug) console.log("----------------------------------");
if(debug) elapsed_time("recieved request");
var send_html = function(err, contents) {
if(debug) elapsed_time("start send_html()");
response.writeHead(200, {'Content-Type': 'text/html' } );
response.end(contents);
if(debug) elapsed_time("end send_html()");
}
if(debug) elapsed_time("start readFile()");
fs.readFile('output.txt', send_html);
if(debug) elapsed_time("end readFile()");
}).listen(8080);
Здесь быстрый тест, который вы можете запустить в терминале (оболочка BASH):
for i in {1..100}; do echo $i; curl http://localhost:8080/; done
Ответ 3
Invoking console.time('label')
запишет текущее время в миллисекундах, затем, позже вызвав console.timeEnd('label')
, покажет продолжительность с этой точки.
Время в миллисекундах будет автоматически напечатано рядом с меткой, поэтому вам не нужно делать отдельный вызов console.log для печати метки:
console.time('test');
//some code
console.timeEnd('test'); //Prints something like that-> test: 11374.004ms
Для получения дополнительной информации см. Документы разработчика Mozilla на console.time
.
Ответ 4
var start = +new Date();
var counter = 0;
for(var i = 1; i < LIMIT; i++){
++counter;
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
if (--counter === 0)
{
var end = +new Date();
console.log("all users saved in " + (end-start) + " milliseconds");
}
});
}
Ответ 5
Для тех, кто хочет получить значение прошедшего времени вместо вывода на консоль:
используйте process.hrtime() в качестве предложения @DDeriso, ниже мой более простой подход:
function functionToBeMeasured() {
var startTime = process.hrtime();
// do some task...
// ......
var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime));
console.log('It takes ' + elapsedSeconds + 'seconds');
}
function parseHrtimeToSeconds(hrtime) {
var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
return seconds;
}
Ответ 6
Старый вопрос, но для простого API и легкого решения; вы можете использовать perfy, который использует внутреннее время реального времени (process.hrtime
).
var perfy = require('perfy');
function end(label) {
return function (err, saved) {
console.log(err ? 'Error' : 'Saved');
console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds
};
}
for (var i = 1; i < LIMIT; i++) {
var label = 'db-save-' + i;
perfy.start(label); // <——— start and mark time
db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label));
}
Обратите внимание, что каждый раз, когда вызывается perfy.end(label)
, этот экземпляр автоматически уничтожается.
Раскрытие: Написал этот модуль, вдохновленный ответом D.Deriso. Docs здесь.
Ответ 7
Удивило, что никто не упомянул новые встроенные библиотеки:
Доступно в Node> = 8.5 и должно быть в Modern Browers
https://developer.mozilla.org/en-US/docs/Web/API/Performance
https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#
Узел 8.5 ~ 9.x(Firefox, Chrome)
// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
await delay(1000);
}
performance.mark('A');
(async ()=>{
await doSomeLongRunningProcess();
performance.mark('B');
performance.measure('A to B', 'A', 'B');
const measure = performance.getEntriesByName('A to B')[0];
// firefox appears to only show second precision.
console.log(measure.duration);
performance.clearMeasures(); // apparently you should remove entries...
// Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();
Ответ 8
Вы можете дать Benchmark.js попробовать. Он поддерживает множество платформ среди них также node.js.
Ответ 9
Вы также можете попробовать exectimer. Это дает вам обратную связь, например:
var t = require("exectimer");
var myFunction() {
var tick = new t.tick("myFunction");
tick.start();
// do some processing and end this tick
tick.stop();
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.myFunction.min()); // minimal tick duration
console.log(t.timers.myFunction.max()); // maximal tick duration
console.log(t.timers.myFunction.mean()); // mean tick duration
console.log(t.timers.myFunction.median()); // median tick duration
[edit] Существует еще более простой способ использовать exectimer, потому что теперь он может обернуть код, который нужно измерить. Ваш код может быть обернут следующим образом:
var t = require('exectimer'),
Tick = t.Tick;
for(var i = 1; i < LIMIT; i++){
Tick.wrap(function saveUsers(done) {
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
done();
});
});
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.saveUsers.min()); // minimal tick duration
console.log(t.timers.saveUsers.max()); // maximal tick duration
console.log(t.timers.saveUsers.mean()); // mean tick duration
console.log(t.timers.saveUsers.median()); // median tick duration
Ответ 10
У меня была такая же проблема при переходе с AWS на Azure
Для express и aws вы уже можете использовать существующее время() и timeEnd()
Для Azure используйте это:
https://github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_azure_aws.js
Эти time() и timeEnd() используют существующую функцию hrtime(), которая дает реальное время с высоким разрешением.
Надеюсь, что это поможет.
Ответ 11
Я бы порекомендовал попробовать NodeTime, который, кажется, подходит для того, что вы пытаетесь сделать.
Ответ 12
И еще один вариант - использовать инструмент express-debug:
express-debug - это инструмент разработки для выражения. Это простое промежуточное программное обеспечение, которое инъецирует полезный отладочный вывод в ваш html, без препятствий.
Он удобно предлагает панель профилирования:
общее время обработки запроса. промежуточное ПО, параметры и время маршрута.
Кроме того. чтобы добавить к приведенным выше ответам, вы можете проверить этот ответ, чтобы включить любой код профилирования только для среды разработки.