Как измерять время, выполняемое функцией для выполнения
Мне нужно получить время выполнения в миллисекундах.
Я изначально задал этот вопрос еще в 2008 году. Принятый ответ тогда было использовать new Date(). getTime() Однако мы все можем сейчас согласиться что использование стандартного performance.now() API больше подходящее. Поэтому я изменяю принятый ответ на этот вопрос.
Ответы
Ответ 1
var t0 = performance.now();
doSomething(); // <---- The function you're measuring time for
var t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
NodeJs
: it is required to import the performance
class
console.time('someFunction');
someFunction(); // Whatever is timed goes between the two "console.time"
console.timeEnd('someFunction');
Примечание:
Строка, передаваемая в методы time()
и timeEnd()
, должна соответствовать
(чтобы таймер завершил работу, как ожидалось).
console.time()
Документация:
- Документация NodeJS относительно
- MDN (клиентская) документация
Ответ 2
использовать new Date(). getTime()
Метод getTime() возвращает число миллисекунд с полуночи 1 января 1970 г.
ех.
var start = new Date().getTime();
for (i = 0; i < 50000; ++i) {
// do something
}
var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);
Ответ 3
Не использовать Date(). Читайте ниже.
Использовать performance.now()
:
<script>
var a = performance.now();
alert('do something...');
var b = performance.now();
alert('It took ' + (b - a) + ' ms.');
</script>
Он работает на:
-
IE 10 ++
-
FireFox 15 ++
-
Chrome 24 ++
-
Safari 8 ++
-
Opera 15 ++
-
Android 4.4 ++
-
и т.д. и т.д.
console.time
может быть жизнеспособным для вас, но он нестандартный & sect;:
Эта функция нестандартная и не соответствует треку стандартов. Не используйте его на производственных площадках, обращенных к Интернету: он не будет работать для каждого пользователя. Там может также быть большая несовместимость между реализациями, и поведение может измениться в будущем.
Помимо поддержки браузера, performance.now
, похоже, имеет потенциал для обеспечения более точных таймингов, поскольку он выглядит как голой версии console.time
.
<rant> Кроме того, НЕ МОЖЕТ использовать Date
для чего-либо, потому что это повлияло на изменения в "системном времени". Это означает, что будет получать недопустимые результаты — например, "отрицательное время" — когда пользователь не имеет точного системного времени:
В октябре 2014 года мои системные часы пошли haywire и угадали, что.... Я открыл Gmail и увидел все мои дневные электронные письма "отправлено 0 минут назад". И я думал, что Gmail должен быть построен инженерами мирового класса из Google.
(Установите системные часы на год назад и перейдите в Gmail, чтобы мы все могли посмеяться. Возможно, когда-нибудь у нас будет Hall of Shame для JS Date
.)
Функция Google Spreadsheet now()
также страдает от этой проблемы.
Единственный раз, когда вы будете использовать Date
, - это время, когда вы хотите показать системное время пользователя . Не когда вы хотите получить время или измерить что-либо.
Ответ 4
Если вам нужно получить время выполнения функции на локальной машине разработки, вы можете использовать инструменты профилирования браузера или консольные команды, такие как console.time()
и console.timeEnd()
.
Во всех современных браузерах есть встроенные JavaScript-профиляторы. Эти профилировщики должны давать наиболее точные измерения, так как вам не нужно изменять существующий код, что может повлиять на время выполнения функции.
Чтобы просмотреть свой JavaScript:
- В Chrome нажмите F12 и выберите вкладку "Профили", а затем "Собрать профиль процессора JavaScript".
- В Firefox установите/откройте Firebug и нажмите кнопку "Профиль".
- В IE 9 + нажмите F12, нажмите Script или Profiler (в зависимости от вашей версии IE).
В качестве альтернативы, на вашей машине разработки вы можете добавить приборы в свой код с помощью console.time()
и console.timeEnd()
. Эти функции, поддерживаемые в Firefox11 +, Chrome2 + и IE11 +, сообщают о таймерах, которые вы запускаете/останавливаете с помощью console.time()
. time()
принимает определяемое пользователем имя таймера в качестве аргумента, а timeEnd()
затем сообщает о времени выполнения с момента запуска таймера:
function a() {
console.time("mytimer");
... do stuff ...
var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF
}
Обратите внимание, что только Firefox возвращает истекшее время в вызове timeEnd()
. Другие браузеры просто сообщают результат консоли разработчика: возвращаемое значение timeEnd()
равно undefined.
Если вы хотите получить время выполнения функции в дикой природе, вам придется обрабатывать свой код. У вас есть пара вариантов. Вы можете просто сохранить время начала и окончания, запросив new Date().getTime()
:
function a() {
var start = new Date().getTime();
... do stuff ...
var end = new Date().getTime();
var dur = end - start;
}
Однако объект Date
имеет только миллисекундное разрешение и будет зависеть от изменений в системных часах ОС. В современных браузерах есть лучший вариант.
Лучшим вариантом является использование Высокого разрешения времени, ака window.performance.now()
. now()
лучше традиционного Date.getTime()
двумя важными способами:
-
now()
является двойным с субмиллисекундным разрешением, которое представляет собой число миллисекунд с момента начала навигации по странице. Он возвращает количество микросекунд в дробном (например, значение 1000.123 составляет 1 секунду и 123 микросекунды).
-
now()
монотонно возрастает. Это важно, так как Date.getTime()
может прыгать вперед или даже назад при последующих вызовах. Примечательно, что если время системы ОС обновляется (например, синхронизация атомных часов), также обновляется Date.getTime()
. now()
гарантированно будет монотонно увеличиваться, поэтому на него не влияет время системы ОС - всегда будет время настенных часов (если ваши настенные часы не являются атомарными...).
now()
может использоваться почти в каждом месте, где new Date().getTime()
, + new Date
иt Date.now()
. Исключением является то, что Date
и now()
раза не смешиваются, поскольку Date
основан на unix-epoch (число миллисекунд с 1970 года), а now()
- количество миллисекунд с момента начала навигации по вашей странице (поэтому оно будет намного меньше Date
).
Вот пример использования now()
:
function a() {
var start = window.performance.now();
... do stuff ...
var end = window.performance.now();
var dur = end - start;
}
now()
поддерживается в Chrome stable, Firefox 15+ и IE10. Существует также несколько полиполков.
Еще один параметр для измерения времени выполнения в дикой природе - UserTiming. UserTiming ведет себя аналогично console.time()
и console.timeEnd()
, но использует ту же самую временную метку высочайшего разрешения, которая используется now()
(поэтому вы получаете мономически увеличивающиеся часы в миллисекундах) и сохраняет метки времени и длительности в PerformanceTimeline.
UserTiming имеет понятия меток (временных меток) и мер (продолжительности). Вы можете определить столько из них, сколько хотите, и они отображаются на PerformanceTimeline.
Чтобы сохранить метку времени, вы вызываете mark(startMarkName)
. Чтобы получить длительность с момента вашей первой отметки, вы просто вызываете measure(measurename, startMarkname)
. Затем продолжительность сохраняется в PerformanceTimeline вместе с вашими отметками.
function a() {
window.performance.mark("start");
... do stuff ...
window.performance.measure("myfunctionduration", "start");
}
// duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];
UserTiming доступен в IE10 + и Chrome25+. Существует также polyfill (который я написал).
Ответ 5
Чтобы получить точные значения, вы должны использовать Интерфейс производительности. Он поддерживается в современных версиях Firefox, Chrome, Opera и IE. Вот пример того, как это можно использовать:
var performance = window.performance;
var t0 = performance.now();
doWork();
var t1 = performance.now();
console.log("Call to doWork took " + (t1 - t0) + " milliseconds.")
Date.getTime()
или console.time()
не подходят для измерения точного времени выполнения. Вы можете использовать их, если для вас приблизительная приблизительная оценка. По приблизительной оценке я имею в виду, что вы можете получить сдвиг в 15-60 мс от реального времени.
Проверьте этот блестящий пост на измерение времени выполнения в JavaScript. Автор также дает пару ссылок о точности времени JavaScript, которые стоит прочитать.
Ответ 6
Использовать Firebug, включить как консоль, так и Javascript. Нажмите "Профиль". Обновить. Еще раз нажмите "Профиль". Просмотрите отчет.
Ответ 7
var StopWatch = function (performance) {
this.startTime = 0;
this.stopTime = 0;
this.running = false;
this.performance = performance === false ? false : !!window.performance;
};
StopWatch.prototype.currentTime = function () {
return this.performance ? window.performance.now() : new Date().getTime();
};
StopWatch.prototype.start = function () {
this.startTime = this.currentTime();
this.running = true;
};
StopWatch.prototype.stop = function () {
this.stopTime = this.currentTime();
this.running = false;
};
StopWatch.prototype.getElapsedMilliseconds = function () {
if (this.running) {
this.stopTime = this.currentTime();
}
return this.stopTime - this.startTime;
};
StopWatch.prototype.getElapsedSeconds = function () {
return this.getElapsedMilliseconds() / 1000;
};
StopWatch.prototype.printElapsed = function (name) {
var currentName = name || 'Elapsed:';
console.log(currentName, '[' + this.getElapsedMilliseconds() + 'ms]', '[' + this.getElapsedSeconds() + 's]');
};
Тест
var stopwatch = new StopWatch();
stopwatch.start();
for (var index = 0; index < 100; index++) {
stopwatch.printElapsed('Instance[' + index + ']');
}
stopwatch.stop();
stopwatch.printElapsed();
Выход
Instance[0] [0ms] [0s]
Instance[1] [2.999999967869371ms] [0.002999999967869371s]
Instance[2] [2.999999967869371ms] [0.002999999967869371s]
/* ... */
Instance[99] [10.999999998603016ms] [0.010999999998603016s]
Elapsed: [10.999999998603016ms] [0.010999999998603016s]
performance.now() является необязательным - просто передайте false в функцию конструктора StopWatch.
Ответ 8
process.hrtime() доступен в Node.js - он возвращает значение в наносекундах
var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
Ответ 9
Чтобы расширить код vsync дальше, чтобы иметь возможность вернуть timeEnd в качестве значения в NodeJS, используйте этот маленький фрагмент кода.
console.timeEndValue = function(label) { // Add console.timeEndValue, to add a return value
var time = this._times[label];
if (!time) {
throw new Error('No such label: ' + label);
}
var duration = Date.now() - time;
return duration;
};
Теперь используйте такой код:
console.time('someFunction timer');
someFunction();
var executionTime = console.timeEndValue('someFunction timer');
console.log("The execution time is " + executionTime);
Это дает вам больше возможностей. Вы можете сохранить время выполнения, которое будет использоваться для других целей, таких как использование его в уравнениях или сохранение в базе данных, отправленное удаленному клиенту через веб-сайты, обслуживаемые на веб-странице и т.д.
Ответ 10
Вы также можете использовать оператор добавления здесь
var start = +new Date();
callYourFunctionHere();
var end = +new Date();
var time = end - start;
console.log('total execution time = '+ time + 'ms');
Ответ 11
Можно использовать только одну переменную:
var timer = -performance.now();
// Do something
timer += performance.now();
console.log("Time: " + (timer/1000).toFixed(5) + " sec.")
timer/1000
- для перевода миллисекунд в секунды
.toFixed(5)
- обрезать лишние цифры
Ответ 12
Так как console.time
и performance.now
не поддерживаются в некоторых основных браузерах (т.е. IE10), я создал тонкую утилиту, которая использует лучшие доступные методы. Однако ему не хватает обработки ошибок для ложных операций (вызов End()
на не инициализированный таймер).
Используйте его и улучшайте, как хотите.
Performance: {
Timer: {},
Start: function (name) {
if (console && console.time) {
console.time(name);
} else if (window.performance.now) {
this.Timer[name] = window.performance.now();
} else {
this.Timer[name] = new Date().getTime();
}
},
End: function (name) {
if (console && console.time) {
console.timeEnd(name);
} else {
var result;
if (window.performance.now) {
result = window.performance.now() - this.Timer[name];
} else {
result = new Date().getTime() - this.Timer[name];
}
console.log(name + ": " + result);
}
}
}
Ответ 13
Это может вам помочь.
var t0 = date.now(); doSomething(); var t1 = date.now(); console.log("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")
Ответ 14
Спасибо, Ахим Коэльнер, немного расширит ваш ответ:
var t0 = process.hrtime();
//Start of code to measure
//End of code
var timeInMilliseconds = process.hrtime(t0)[1]/1000000; // dividing by 1000000 gives milliseconds from nanoseconds
Обратите внимание, что вы не должны делать ничего, кроме того, что вы хотите измерить (например, console.log
также потребуется время для выполнения и повлияет на тесты производительности).
Обратите внимание, что в порядке измерения времени выполнения асинхронных функций вы должны вставить var timeInMilliseconds = process.hrtime(t0)[1]/1000000;
внутри обратного вызова. Например,
var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;
});
Ответ 15
Здесь декоратор для функций синхронизации
let timed = (f) => (...args)=>{
let start = performance.now();
let ret = f(...args);
console.log('function ${f.name} took ${(performance.now()-start).toFixed(3)}ms')
return ret;
}
Использование:
let test = ()=>{/*does something*/}
test = timed(test) // turns the function into a timed function in one line
test() // run your code as normal, logs 'function test took 1001.900ms'
Если вы используете функции асинхронных вы можете сделать timed
асинхра и добавить await
перед тем F (... арг), и это должно работать на них. Это усложняется, если вы хотите, чтобы один декоратор обрабатывал как функции синхронизации, так и асинхронные функции.
Ответ 16
Пару месяцев назад я собрал свою собственную рутину, которая использует функцию Date.now(), хотя в то время, когда принятый метод выглядел как performance.now() - поскольку объект производительности еще недоступен (встроенный -in) в стабильном выпуске Node.js.
Сегодня я проводил еще несколько исследований и нашел еще один метод синхронизации. Поскольку я также нашел, как использовать это в коде Node.js, я думал, что поделюсь им здесь.
Ниже приведены примеры, приведенные w3c и Node.js:
function functionTimer() {
performance.mark('start')
functionToBeTimed()
performance.mark('end')
performance.measure('Start to End', 'start', 'end')
const measure = performance.getEntriesByName('Start to End')[0]
console.log(measure.duration)
}
НОТА:
Если вы намерены использовать объект performance
в приложении Node.js, вы должны включить следующее require: const { performance } = require('perf_hooks')
Ответ 17
Если вы хотите измерить время между несколькими вещами, которые не вложены, вы можете использовать это:
function timer(lap){
if(lap) console.log('${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms');
timer.prev = performance.now();
}
Подобно console.time(), но проще использовать, если вам не нужно отслеживать предыдущие таймеры.
Если вам нравится синий цвет от console.time(), вы можете использовать эту строку вместо
console.log('${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms', 'color:blue');
// Usage:
timer() // set the start
// do something
timer('built') // logs 'built in: 591.815ms'
// do something
timer('copied') // logs 'copied in: 0.065ms'
// do something
timer('compared') // logs 'compared in: 36.41ms'
Ответ 18
export default class Singleton {
static myInstance: Singleton = null;
_timers: any = {};
/**
* @returns {Singleton}
*/
static getInstance() {
if (Singleton.myInstance == null) {
Singleton.myInstance = new Singleton();
}
return this.myInstance;
}
initTime(label: string) {
this._timers[label] = Date.now();
return this._timers[label];
}
endTime(label: string) {
const endTime = Date.now();
if (this._timers[label]) {
const delta = endTime - this._timers[label];
const finalTime = '${label}: ${delta}ms';
delete this._timers[label];
return finalTime;
} else {
return null;
}
}
}
InitTime связано со string
.
return Singleton.getInstance().initTime(label);//Returns the time init
return Singleton.getInstance().endTime(label);//Returns the total time between init and end
Ответ 19
В моем случае я берусь за использование грамматики и компиляцию ее с помощью babel.
Проблема этого метода заключается в том, что функция должна быть внутри объекта.
Пример кода JS
function timer() {
return (target, propertyKey, descriptor) => {
const start = Date.now();
let oldFunc = descriptor.value;
descriptor.value = async function (){
var result = await oldFunc.apply(this, arguments);
console.log(Date.now() - start);
return result;
}
}
}
// Util function
function delay(timeout) {
return new Promise((resolve) => setTimeout(() => {
resolve();
}, timeout));
}
class Test {
@timer()
async test(timout) {
await delay(timout)
console.log("delay 1");
await delay(timout)
console.log("delay 2");
}
}
const t = new Test();
t.test(1000)
t.test(100)
.babelrc (для babel 6)
{
"plugins": [
"transform-decorators-legacy"
]
}
Ответ 20
Секундомер с накопительными циклами
Работает с сервером и клиентом (Node или DOM), использует Performance
API. Хорошо, когда у вас много маленьких циклов, например, в функции, вызываемой 1000 раз, которая обрабатывает 1000 объектов данных, но вы хотите увидеть, как каждая операция в этой функции складывается в общую сумму.
Так что этот использует глобальный (одиночный) таймер модуля. То же, что и шаблон синглтона класса, чуть проще в использовании, но вы должны поместить его в отдельный файл, например, stopwatch.js
.
const perf = typeof performance !== "undefined" ? performance : require('perf_hooks').performance;
const DIGITS = 2;
let _timers = {};
const _log = (label, delta?) => {
if (_timers[label]) {
console.log('${label}: ' + (delta ? '${delta.toFixed(DIGITS)} ms last, ' : '') +
'${_timers[label].total.toFixed(DIGITS)} ms total, ${_timers[label].cycles} cycles');
}
};
export const Stopwatch = {
start(label) {
const now = perf.now();
if (_timers[label]) {
if (!_timers[label].started) {
_timers[label].started = now;
}
} else {
_timers[label] = {
started: now,
total: 0,
cycles: 0
};
}
},
/** Returns total elapsed milliseconds, or null if stopwatch doesn't exist. */
stop(label, log = false) {
const now = perf.now();
if (_timers[label]) {
let delta;
if(_timers[label].started) {
delta = now - _timers[label].started;
_timers[label].started = null;
_timers[label].total += delta;
_timers[label].cycles++;
}
log && _log(label, delta);
return _timers[label].total;
} else {
return null;
}
},
/** Logs total time */
log: _log,
delete(label) {
delete _timers[label];
}
};
Ответ 21
Наилучшим способом было бы использовать модуль performance hooks
. Несмотря на нестабильность, вы можете mark
определенные области вашего кода и measure
duration
между отмеченными областями.
const { performance, PerformanceObserver } = require('perf_hooks');
const measures = []
const obs = new PerformanceObserver(list => measures.push(...list.getEntries()));
obs.observe({ entryTypes: ['measure'] });
const getEntriesByType = cb => cb(measures);
const doSomething = val => {
performance.mark('beginning of the process');
val *= 2;
performance.mark('after multiplication');
performance.measure('time taken', 'beginning of the process', 'after multiplication');
getEntriesByType(entries => {
entries.forEach(entry => console.log(entry));
})
return val;
}
doSomething(4);
Попробуй здесь
Ответ 22
Есть несколько способов достижения этой цели:
-
используя console.time
console.time('function');//run the function in between these two lines for that you need to measure time taken//by the function. ("ex. function();") console.timeEnd('function');
-
это самый эффективный способ: использование performance.now()
ех. var v1 = performance.now();//run the function here for which you have top measure the time var v2 = performance.now(); console.log("total time taken = "+(v2-v1)+"milliseconds";
-
используйте + (добавить оператор) или getTime()
var h2 = +new Date();//or var h2 = new Date().getTime(); for(i=0;i<500;i++) {//do something} var h3 = +new Date();//or var h3 = new Date().getTime(); var timeTaken = h3-h2; console.log("time ====", timeTaken);
Вот что происходит, когда вы применяете унарный оператор плюс к экземпляру Date: Получите значение рассматриваемого экземпляра Date. Преобразуйте его в число.
ПРИМЕЧАНИЕ: getTime() дает лучшую производительность, чем унарный оператор +.
Ответ 23
const { performance } = require('perf_hooks');
function addUpTo(n) {
let total = 0;
for (let i = 1; i <= n; i++) {
total += i;
}
return total;
}
let t1 = performance.now();
addUpTo(1000000000);
let t2 = performance.now();
console.log('Time elapsed: ${(t2 - t1) / 1000} seconds');
// Time elapsed: 1.1261566010713577 seconds
Ответ 24
С производительностью
NodeJs: требуется импортировать класс производительности
var time0 = performance.now(); // Store the time at this point into time0
yourFunction(); // The function you're measuring time for
var time1 = performance.now(); // Store the time at this point into time1
console.log("youFunction took " + (time1 - time0) + " milliseconds to execute");
Использование console.time
console.time('someFunction');
someFunction(); // Whatever is timed goes between the two "console.time"
console.timeEnd('someFunction');
Ответ 25
Как указано ранее, проверьте и используйте встроенный таймер. Но если вы хотите или хотите написать свой собственный, вот мои два цента:
//=-=|Source|=-=//
/**
* JavaScript Timer Object
*
* var now=timer['elapsed']();
* timer['stop']();
* timer['start']();
* timer['reset']();
*
* @expose
* @method timer
* @return {number}
*/
timer=function(){
var a=Date.now();
b=0;
return{
/** @expose */
elapsed:function(){return b=Date.now()-a},
start:function(){return a=Date.now()},
stop:function(){return Date.now()},
reset:function(){return a=0}
}
}();
//=-=|Google Advanced Optimized|=-=//
timer=function(){var a=Date.now();b=0;return{a:function(){return b=Date.now()-a},start:function(){return a=Date.now()},stop:function(){return Date.now()},reset:function(){return a=0}}}();
Компиляция прошла успешно!
- Исходный размер: 219 байт gzipped (405 байт без сжатия)
- Скомпилированный размер: 109 байт gzipped (187 байт без сжатия)
- Сохранено на 50.23% от размера gzip (53.83% без gzip
Ответ 26
Принятый ответ неправильный!
Поскольку JavaScript является асинхронным, значения переменной конца принятого ответа были бы неправильными.
var start = new Date().getTime();
for (i = 0; i < 50000; ++i) {
// JavaScript is not waiting until the for is finished !!
}
var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);
Выполнение этого параметра может быть очень быстрым, поэтому вы не можете видеть, что результат неверен. Вы можете проверить его с помощью кода, выполняющего некоторый запрос:
var start = new Date().getTime();
for (i = 0; i < 50000; ++i) {
$.ajax({
url: 'www.oneOfYourWebsites.com',
success: function(){
console.log("success");
}
});
}
var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);
Таким образом, предупреждение будет запрашиваться очень быстро, но в консоли вы увидите, что запросы ajax продолжаются.
Вот как вы должны это сделать: https://developer.mozilla.org/en-US/docs/Web/API/Performance.now