Мне нужно получить время выполнения в миллисекундах.
Первоначально я задал этот вопрос еще в 2008 году. Принятым ответом тогда было использование new Date().getTime() Однако сейчас мы все согласны с тем. что использование стандартного API performance.now() более целесообразным. Поэтому я меняю принятый ответ на этот.
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
: требуется импортировать классperformance
.
console.time('someFunction');
someFunction(); // Whatever is timed goes between the two "console.time"
console.timeEnd('someFunction');
Примечание:
Строка, передаваемая методам time()
и timeEnd()
должна совпадать
(чтобы таймер завершился, как ожидается).
console.time()
документация:
использовать new Date().getTime()
Метод getTime() возвращает количество миллисекунд, прошедших с полуночи 1 января 1970 года.
ex.
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);
Использовать 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 ++
Опера 15 ++
Android 4.4 ++
console.time
может быть жизнеспособным для вас , но это нестандартно & sect;:
Эта функция нестандартна и не соответствует стандартам. Не используйте его на производственных сайтах, стоящих перед Интернетом: он не будет работать для каждого пользователя. Также может быть большая несовместимость между реализациями ** и поведение может измениться в будущем.
Помимо поддержки браузера, performance.now
, кажется, имеет потенциал для обеспечения более точных таймингов, поскольку это, по-видимому, версия `console.time' с «голыми костями».
& Лт; hr >
< rant > Кроме того, ** НИКОГДА не используйте `Date` для * чего-либо ***, потому что на него влияют изменения в «системном времени». Это означает, что мы ** получим ** недействительные результаты & mdash, например, "отрицательное время" & mdash; когда у пользователя нет точного системного времени:В октябре 2014 года мои системные часы вышли из строя и угадайте, что .... Я открыл Gmail и увидел все электронные письма моего дня ", отправленные 0 минут назад ". И я думал, что Gmail должен быть построен инженерами мирового класса из Google.......
(Установите системные часы на год назад и перейдите на Gmail, чтобы мы все могли посмеяться. Возможно, когда-нибудь у нас будет Зал позора для JS Date
.)
Функция Google Spreadsheet now ()
также страдает от этой проблемы.
Единственный раз, когда вы будете использовать Date
, это когда вы хотите показать пользователю его системное время. Не тогда, когда вы хотите получить время или измерить что-либо.
Если вам нужно получить время выполнения функций на локальном компьютере разработки , вы можете использовать инструменты профилирования вашего браузера или консольные команды, такие как console.time ()
и console.timeEnd ()
.
Все современные браузеры имеют встроенные профилировщики JavaScript. Эти профилировщики должны давать наиболее точное измерение, так как вам не нужно изменять существующий код, что может повлиять на время выполнения функции.
Чтобы описать ваш JavaScript:
В качестве альтернативы на вашем компьютере разработки вы можете добавить инструменты в свой код с помощью 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 ()
не определено.
Если вы хотите получить время выполнения функции в дикой природе , вам придется прибородовать свой код. У вас есть пара вариантов. Вы можете просто сохранить время начала и окончания, запросив 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
и tDate.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 имеет понятия mark (timestamps) и merasures (durations). Вы можете определить столько, сколько захотите, и они отображаются на 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];
Пользовательский тайминг доступен в IE10 + и Chrome25 +. Также доступен polyfill (который я написал).
Чтобы получить точные значения, вы должны использовать интерфейс Performance. Поддерживается в современных версиях 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 мс сдвига от реального времени.
Проверьте этот блестящий post по измерению времени выполнения в JavaScript. Автор также дает пару ссылок о точности времени JavaScript, которое стоит прочитать.
Используйте Firebug, включите консоль и Javascript. Нажмите Профиль. Перезагрузите. Снова нажмите Профиль. Просмотрите отчет.
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]');
};
Benchmark
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 ()][1] является необязательным - просто передайте false в функцию конструктора StopWatch.
[1]: http://updates.html5rocks.com/2012/08/When-milliseconds-are-not-enough-performance-nowhttp://updates.html5rocks.com/2012/08/When-milliseconds-are- не достаточно-достаточно-производительность-сейчас
process.hrtime () доступен в Node.js - возвращает значение в наносекундах
var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
Вы можете использовать добавить оператор также здесь
var start = +new Date();
callYourFunctionHere();
var end = +new Date();
var time = end - start;
console.log('total execution time = '+ time + 'ms');
Чтобы расширить код 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);
Это дает вам больше возможностей. Вы можете сохранить время выполнения, которое будет использоваться для более широких целей, таких как использование его в уравнениях или хранение в базе данных, отправка удаленному клиенту через веб-кассеты, обслуживание на веб-странице и т. Д.
Можно использовать только одну переменную:
var timer = -performance.now();
// Do something
timer += performance.now();
console.log("Time: " + (timer/1000).toFixed(5) + " sec.")
timer / 1000
- для преобразования миллисекунд в секунды
.toFixed (5)
- обрезать дополнительные цифры
Поскольку 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);
}
}
}
Это может помочь вам.
var t0 = date.now () ; doSomething () ; var t1 = date.now () ; consol.log («Звонить, чтобы сделать что-то заняло приблизительно» + (t1 - t0) / 1000 + «секунды.«)
Вот декоратор для временных функций
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'
Если вы используете функции async, вы можете создать timed
async и добавить await
перед f (...args), и это должно работать для тех. Это усложняется, если вы хотите, чтобы один декоратор обрабатывал функции синхронизации и асинхронизации.
Спасибо, Ахим Коелнер, немного расширит ваш ответ:
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;
});
Пару месяцев назад я собрал свою собственную подпрограмму, которая выполняет функцию с использованием Date.now () - хотя в то время принятый метод казался «performance.now () -» потому что объект производительности еще не доступен (встроенный) в стабильном выпуске 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, вы должны включить следующее требование:
const {performance} = require ('perf_hooks')
Если вы хотите измерить время между несколькими вещами, которые не вложены, вы можете использовать это:
function timer(lap){
if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`);
timer.prev = performance.now();
}
Похож на consol.time (), но более простое использование, если вам не нужно отслеживать предыдущие таймеры.
Если вам нравится синий цвет от consol.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'
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); // Возвращает время init
return Singleton.getInstance () .endTime (label); // Возвращает общее время между init и end
В моем случае я предпочитаю использовать @ gramnary suger и скомпилировать его с 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 (для Вавилона 6)
{
"plugins": [
"transform-decorators-legacy"
]
}
Работает с сервером и клиентом (узел или DOM), использует API Performance
Хорошо, когда у вас много маленьких циклов, например. в функции, называемой 1000 раз, которая обрабатывает 1000 объектов данных, но вы хотите увидеть, как каждая операция в этой функции складывается в общую сумму.
Таким образом, этот использует модуль глобального (синглтонного) таймера. То же, что и у однотонного шаблона класса, просто немного проще в использовании, но вам нужно поместить это в отдельный, например. Файл stopwatch.js
.
`` javascript const perf = тип производительности !== "не определено" ? производительность: require ('perf_hooks') .performance ; const DIGITS = 2;
пусть _timers = {{{}}} ;
const _log = (метка, дельта?) = > {
if (_timers [label]) {
consol.log ($ {label}:
+ (дельта ? $ {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]) { если (!_timers [label] .started) { _timers [label] .started = сейчас ; } } еще { _timers [label] = { начал: сейчас всего: 0, циклы: 0 }; } }, / * Возвращает общее количество прошедших миллисекунд или ноль, если секундомер не существует. / stop (label, log = false) { const now = perf.now () ; if (_timers [label]) { пусть дельта; if (_timers [label] .started) { delta = сейчас - _timers [label] .started ; _timers [label] .started = null ; _timers [label] .total + = дельта ; _timers [label] .cycles ++ ; } журнал & & _log (ярлык, дельта) ; return _timers [label] .total ; } еще { вернуть ноль; } }, / * Журналы общее время / журнал: _log, delete (label) { удалить _timers [label] ; } };