Как измерить время, затрачиваемое функцией на выполнение

Мне нужно получить время выполнения в миллисекундах.

I originally asked this question back in 2008. The accepted answer then was to use new Date().getTime() However, we can all agree now that using the standard performance.now() API is more appropriate. I am therefore changing the accepted answer to this one.

Часто заявление о том, чего вы пытаетесь достичь с помощью времени выполнения, может оказаться гораздо более полезным, чем ответ на один вопрос. В наши дни использование профилирования в инструментах Firebug или Chrome Dev часто является гораздо лучшим способом найти код, который поглощает ваш процессор.

oligofren 06.03.2013 14:04
performance.now() не работает в Node. new Date().getTime() будет работать в Node.
Ryan Walker 12.09.2018 01:50

номер 1000 за голос woop woop: D

Kiksen 23.09.2019 11:08

@RyanWalker или еще более простой Date.now(), он также работает в узле

f278f1b2 01.11.2019 18:18

@oligofren - Иногда вам может понадобиться захватить эти данные. У меня ситуация, когда я пишу это в indexedDB

ThomasRones 08.04.2020 07:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1 349
5
781 502
26
Перейти к ответу Данный вопрос помечен как решенный

Ответы 26

Используйте Firebug, включите консоль и Javascript. Щелкните Профиль. Перезагрузить. Снова щелкните Профиль. Просмотрите отчет.

Хороший совет, но, очевидно, работает только для FF. Мы часто хотим сравнить скорости браузеров ... :-)

PhiLho 24.11.2008 14:27

В новом Firebuq они скрывают эти параметры в меню, используйте CTRL + SHIFT + P или console.profile (); console..profileEnd ()

user956584 29.02.2012 12:25

Chrome теперь поддерживает console.time() и console.timeEnd().

julien_c 15.03.2012 15:01

используйте новая дата (). getTime ()

The getTime() method returns the number of milliseconds since midnight of January 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);

Обратите внимание, что вы можете заменить вызов getTime () на + new Date (): var start = + new Date (); // делаем вещи alert ("Время выполнения:" + (+ new Date ()) - start);

J c 24.11.2008 16:00

Сроки неточны, потому что Дата не предназначена для этой функции. Я собираюсь выделиться здесь жирным шрифтом и сказать, что вам следует использовать пример vsync, если вам нужно точное время. Хотя работает только в банкоматах Chrome и Firefox.

Ash Blue 05.05.2012 06:17

Остерегайтесь, getMilliseconds () дает вам долю миллисекунды от текущей секунды. Если вы замените getTime () на getMilliseconds (), вы можете получить отрицательный результат, если пересечете секунду.

RickyA 10.01.2013 19:47

Ответ vsync намного более правильный по сегодняшним стандартам, и использование Date () может привести к отображению очень ошибочных результатов, особенно на платформе Windows, где результаты могут быть округлены + округлены до ближайшей границы 15 мс, что приводит к странным вещам, например Тайминги 0 мс на крошечных битах кода.

oligofren 06.03.2013 13:59

@AshBlue, мы должны использовать window.performance.now. См. stackoverflow.com/a/15641427/632951

Pacerier 02.11.2013 06:17

Следует отметить, что в NodeJS консольные методы time() и timeEnd действительно используют объект Date(). Источник: github.com/joyent/node/blob/master/lib/console.js

Levi Roberts 17.12.2013 23:27

Хотя это неверно для определения прошедшего времени выполнения вашего кода, я считаю, что он работает для вычисления прошедшего времени в других контекстах. Например, у меня есть сервер Node.js, который принимает сигналы датчиков, регистрирует дату события с помощью new Date (). Затем я могу вычислить истекшее время события, например, с помощью метода, описанного в этом ответе. Что вы думаете, ребята?

blaze 09.03.2014 01:51

вместо 'var start = new Date (). getTime ();' и 'var end = new Date (). getTime ();' , мы могли бы использовать var start = Date.now (); и 'var end = Date.now ();' избежание (/ уменьшение) разницы во времени, возникающей при мог, с помощью Date (). getTime (), потому что Date.now () работает намного быстрее.

SoftwareTester 05.06.2014 01:52

Фактически, использование getTime() (по крайней мере, в современных JS-движках) не нужно. Вычитание двух объектов Date() дает число в миллисекундах.

pbanka 27.08.2015 20:02

Это не работает, если в функции есть обратные вызовы.

avishek gurung 09.07.2016 09:49

Помните, что сама операция по созданию new Date() является дорогостоящей и может сильно повлиять на общую производительность, например, при попытке синхронизировать отдельные части цикла на большом количестве элементов.

Thierry J. 20.10.2017 15:39

Все ответы здесь неверны и делают неверное предположение, что время выполнения функции постоянно для одного и того же входа. В основном это было так примерно до 2007 года. Это игнорирует тот факт, что все современные JS-компиляторы во всех современных браузерах (и в Node) имеют устранение мертвого кода и своевременную компиляцию.

Benjamin Gruenbaum 06.06.2018 12:10

@ThierryJ. - создание дат намного дешевле, чем использование Performance.nowпосмотреть тесты

vsync 17.09.2018 13:26

Это вполне возможно. Я просто говорю, что если вы создадите дату внутри цикла, который хотите отсчитать, с единственной целью отследить часть этого цикла, результаты на самом деле будут хуже, чем без кода для отсчета времени цикла.

Thierry J. 18.09.2018 17:48
Ответ принят как подходящий

Используя performance.now ():

var t0 = performance.now()

doSomething()   // <---- The function you're measuring time for 

var t1 = performance.now()
console.info("Call to doSomething took " + (t1 - t0) + " milliseconds.")

NodeJs: it is required to import the performance class


Использование console.time: (нестандартный) (уровень жизни)

console.time('someFunction')

someFunction() // Whatever is timed goes between the two "console.time"

console.timeEnd('someFunction')

Примечание:
Строка, передаваемая в методы time() и timeEnd(), должна соответствовать
(для таймер, чтобы закончить, как ожидалось).

console.time() documentations:

  1. NodeJS documentation regarding
  2. MDN (client-side) documentation

Теперь он также поддерживается инструментами разработчика Chrome.

julien_c 15.03.2012 15:00

Насколько я понимаю, в настоящее время это лучший способ получить точные данные о времени.

Ash Blue 05.05.2012 06:18

Разве вам не нужно выполнять функцию между этими двумя операторами? Теперь вы измеряете время, необходимое для его определения, а не для его выполнения. Поправьте меня если я ошибаюсь...

Cristian 05.09.2012 02:06

Ссылка на статью MDN об этой функции: developer.mozilla.org/en-US/docs/DOM/console.time

nullability 19.02.2013 21:19

Можно ли определить глобальный таймер при запуске скрипта. Тогда узнать разницу между текущим временем и запуском скрипта на каждом шаге?

trante 28.05.2013 19:03

@transte - да, см. ответ Dayong внизу

vsync 28.05.2013 20:24

Можно ли получить значение console.timeEnd ()? Я хочу суммировать несколько значений.

Sam Dutton 19.06.2013 18:34

да, вы можете сделать `totalTime + = console.timeEnd ('timer') 'и сделать это для каждого таймера

vsync 19.06.2013 19:28

totalTime + = console.timeEnd ('timer'), похоже, не работает на Node. Посмотрите мой ответ о том, как заставить это работать в Node.

Levi Roberts 04.08.2013 08:24

Кстати, если вы работаете в Chrome - убедитесь, что вы случайно не установили неправильные фильтры сообщений журнала. timeEnd () регистрирует сообщения как сообщения консоли «Отладка». Отправил меня в погоню за дикими гусями ...

Ilan 14.10.2013 18:16

Это хороший вариант, но console.timeEnd () по-прежнему не является стандартом. Используйте Performance.now, который рекомендуется.

Sanjeev 25.01.2015 15:14

Какие факторы определяют эту скорость? 2 + 2 не всегда дает одно и то же время ... Почему?

Squirrl 08.04.2015 10:16

@Squirrl - эта ветка посвящена измерению времени, а не тому, "почему" все так, как есть. Это будет предметом совершенно новой дискуссии. Короче говоря, разница во времени связана с тем, что у вашего процессора есть циклы, а не каждый раз, когда вы запускаете команду, он выделяет ей одинаковое количество ресурсов.

vsync 21.04.2015 00:04

@vsync Спасибо! Есть ли способ измерить, в каком цикле находится мой процессор, или количество ресурсов, выделенных для моей функции, чтобы вызов performance.now () или любой метод на 2 + 2 каждый раз давал одно и то же время / мощность? Я знаю, это странный вопрос. Если бы я знал, как это правильно сформулировать, я бы спросил формально. Спасибо. jsfiddle.net/uzyk8poh

Squirrl 22.04.2015 16:18

@Squirrl - не думаю. компьютеры имеют слишком много вещей, отправляемых на процессор каждую секунду. это как иногда 10 человек разговаривают с вами одновременно, а через секунду - миллион. Вы не можете просто сказать всем, чтобы они заткнулись, чтобы сосредоточиться только на одном человеке, это не так.

vsync 22.04.2015 16:52

Console.timeEnd в nodeJS возвращает undefined.

programmer5000 24.02.2017 21:27

Это текущее состояние производительности .now () The timestamp is not actually high-resolution. To mitigate security threats such as Spectre, browsers currently round the result to varying degrees. (Firefox started rounding to 2 milliseconds in Firefox 59.) Some browsers may also slightly randomize the timestamp. The precision may improve again in future releases; browser developers are still investigating these timing attacks and how best to mitigate them.

miknik 14.07.2018 20:59

@miknik - Date.now() подходит для большинства случаев и запускает намного быстрее.

vsync 14.07.2018 21:25

@RyanWalker - да, вам просто нужно потребовать performance. увидеть это отвечать

vsync 12.09.2018 12:03

@vsync Да, если у вас все в порядке, включая больше зависимостей. Я должен был пояснить, что они изначально не работают; Я предпочитаю минимальные зависимости.

Ryan Walker 12.09.2018 20:24

Что, если я запускаю асинхронную функцию? Например, функция jQuery $.getJSON()?

dcangulo 17.09.2018 07:57

Функция jQuery ajax возвращает обещания, чтобы вы могли вычислить разность времени внутри метода обещаний always jQuery. Я бы предложил измерять время, необходимое для получения данных с сервера на самом сервере, и измерять только синхронизированное время выполнения на стороне клиента. в любом случае, если вы проверяете, сколько времени потребовалось для выполнения какой-то очень большой функции, вам нужно изменить свое мышление относительно того, что именно вы измеряете, и, возможно, разделить свои измерения на асинхронные и синхронизированные.

vsync 17.09.2018 13:04

Для этого я создал полезный легкий модуль - github.com/ngduc/mstime

ngduc 04.10.2018 19:55

console.time теперь является «жизненным стандартом» (console.spec.whatwg.org/#time), и этот ответ следует обновить, чтобы отразить это.

Johann 14.11.2018 04:14

Несколько таймеров даже с разными именами увеличивают время. Можно ли их полностью разделить?

dari0h 23.07.2020 18:11

Не используйте 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 может быть жизнеспособным для тебя, но это нестандартный §:

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

Помимо поддержки браузера, performance.now, похоже, имеет потенциал для обеспечения более точных таймингов, поскольку это, по-видимому, простая версия console.time.


<rant> Также, НИКОГДА не используйте Date для что-нибудь, потому что на него влияют изменения "системного времени". Это означает, что мы воля получаем недопустимые результаты - например, «отрицательное время» - когда у пользователя нет точного системного времени:

On Oct 2014, my system clock went haywire and guess what.... I opened Gmail and saw all of my day's emails "sent 0 minutes ago". And I'd thought Gmail is supposed to be built by world-class engineers from Google.......

(Установите системные часы на год назад и перейдите в Gmail, чтобы мы все могли хорошо посмеяться. Возможно, когда-нибудь у нас будет зал позора для JS Date.)

Функция Google Spreadsheet now() также страдает от этой проблемы.

Единственный раз, когда вы будете использовать Date, - это когда вы хотите показать пользователю системное время его. Не тогда, когда вы хотите получить в время или что-нибудь измерить.

Именно то, что я искал! Я хочу иметь возможность складывать несколько раз, но не могу этого сделать с консольным временем.

Ray 29.09.2013 17:33

обратите внимание, что это пока не поддерживается в сафари: developer.mozilla.org/en-US/docs/Web/API/Performance.now ()

Akos K 02.11.2013 01:11

Я использую Firebug Profile и performance.now (), и они оба работают хорошо. Performance.now () подтверждает мой результат из профиля.

Vincent Jia 11.02.2014 14:01

Не работает в моем самом большом зависании, которым является IE7 (корпоративные клиенты). Меня не волнует измерение производительности в Chrome, это всегда молниеносно.

Nick 03.03.2014 22:27

Это лучший способ, чем console.time ().

Sanjeev 25.01.2015 15:15

Примечание: старые реализации и полифилы используют Date.now.

programmer5000 24.02.2017 21:34

Не работает в Windows Script Hosting. Итак, нужно придерживаться getTime ().

HaLeiVi 25.02.2017 01:02

Да, это работает лучше, но используется Date.now (), потому что Node.js (не серверный) не поддерживает ответ, приведенный здесь или с помощью vsync.

user8385393 19.05.2020 14:59

О твоей разглагольствовании о Date - что бы ты порекомендовал в качестве альтернативы? Отправка текущей даты с помощью вашего скрипта явно не работает, как и получение ее из-за сетевой задержки, поэтому какое решение вы придумали?

Simon 23.09.2020 09:36

Чтобы расширить код 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.info("The execution time is " + executionTime);


Это дает вам больше возможностей. Вы можете сохранить время выполнения, чтобы использовать его для других целей, например, использовать его в уравнениях или сохранить в базе данных, отправить удаленному клиенту через веб-сокеты, обслужить на веб-странице и т. д.

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.info(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.

Если вам нужно получить время выполнения функции на вашей локальной машине разработки, вы можете использовать инструменты профилирования вашего браузера или консольные команды, такие как console.time() и console.timeEnd().

Все современные браузеры имеют встроенные профилировщики JavaScript. Эти профилировщики должны давать наиболее точные измерения, поскольку вам не нужно изменять существующий код, что может повлиять на время выполнения функции.

Чтобы профилировать свой JavaScript:

  • В Хром нажмите F12 и выберите вкладку Профили, затем Соберите профиль процессора JavaScript.
  • В Fire Fox установите / откройте Firebug и нажмите кнопку Профиль.
  • В IE 9+ нажмите F12, щелкните Сценарий или Профайлер (в зависимости от вашей версии 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() не определено.

Если вы хотите узнать время выполнения функции в реальном времени, вам придется инструментировать свой код. У вас есть пара вариантов. Вы можете просто сохранить время начала и окончания, запросив 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() по двум важным причинам:

  1. now() - это двойное число с субмиллисекундным разрешением, которое представляет количество миллисекунд с начала навигации по странице. Он возвращает количество микросекунд в дробной части (например, значение 1000,123 составляет 1 секунду и 123 микросекунды).

  2. now() монотонно увеличивается. Это важно, поскольку Date.getTime() может выполнять переход возможно вперед или даже назад при последующих вызовах. Примечательно, что если системное время ОС обновляется (например, синхронизация атомных часов), Date.getTime() также обновляется. now() всегда будет монотонно увеличиваться, поэтому на него не влияет системное время ОС - это всегда будет время настенных часов (при условии, что ваши настенные часы не атомные ...).

now() можно использовать почти везде, где есть new Date().getTime(), + new Date и Date.now(). Исключением является то, что времена Date и now() не смешиваются, поскольку Date основан на эпоха unix (количество миллисекунд с 1970 года), а now() - это количество миллисекунд с момента начала навигации по вашей странице (поэтому оно будет намного меньше, чем Date). .

Вот пример использования now():

function a() {
  var start = window.performance.now();
   ... do stuff ...
  var end = window.performance.now();
  var dur = end - start;
}

now() поддерживается в стабильной версии Chrome, Firefox 15+ и IE10. Также доступны несколько полифиллы.

Еще один вариант измерения времени выполнения в дикой природе - UserTiming.. UserTiming ведет себя аналогично console.time() и console.timeEnd(), но использует ту же метку времени высокого разрешения, что и now() (так что вы получаете монотонно увеличивающиеся часы на субмиллисекунду), и сохраняет метки времени и длительности в Производительность.

UserTiming имеет концепции Метки (временные метки) и меры (длительности). Вы можете определить любое количество из них, и они отображаются в Производительность.

Чтобы сохранить отметку времени, вы звоните 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 +. Также доступен полифил (о котором я писал).

Отличный и самый актуальный ответ ИМХО :) Было бы даже лучше с небольшим редактированием. Я бы сказал, что пользовательское время - это не «еще один вариант» для измерения, но в предпочтительный вариант, когда тестирование не выполняется на самой машине разработки. С вашим полифилом он работает во всех браузерах. И скрытие деталей и шаблонов performance.now и Date - причина его существования.

hashchange 19.07.2014 14:10

Как указывалось ранее, проверьте и используйте встроенный таймер. Но если вы хотите или вам нужно написать свой собственный, вот мои два цента:

//=-=|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 байт в сжатом виде (405 байт без сжатия).
  • Скомпилированный размер: 109 байт в сжатом виде (187 байт без сжатия)
  • Сэкономлено 50,23% от размера gzip-архива (53,83% без gzip

Поскольку 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.info(name + ": " + result);
        }
    }
}

Принятый ответ: неправильный!

Поскольку JavaScript является асинхронным, значения переменной end принятого ответа будут неправильными.

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); 

Выполнение for может быть очень быстрым, поэтому вы не увидите, что результат неправильный. Вы можете проверить это с помощью кода, выполняющего некоторый запрос:

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
  $.ajax({
    url: 'www.oneOfYourWebsites.com',
    success: function(){
       console.info("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

Это не из-за цикла for. Цикл for будет ждать, пока последний цикл не перейдет к исходному коду. Вызовы AJAX являются асинхронными. Есть и другие асинхронные функции. Но цикл for не выполняется асинхронно.

Scriptlabs 12.03.2015 22:21

Чтобы получить точные значения, вы должны использовать Интерфейс производительности. Он поддерживается в современных версиях Firefox, Chrome, Opera и IE. Вот пример того, как это можно использовать:

var performance = window.performance;
var t0 = performance.now();
doWork();
var t1 = performance.now();
console.info("Call to doWork took " + (t1 - t0) + " milliseconds.")

Date.getTime() или console.time() не подходят для измерения точного времени выполнения. Вы можете использовать их, если вам подходит быстрая приблизительная оценка. По приблизительной оценке я имею в виду, что вы можете получить сдвиг на 15-60 мс от реального времени.

Проверьте этот блестящий Почта по измерению времени выполнения в JavaScript. Автор также дает пару ссылок о точности времени JavaScript, которые стоит прочитать.

process.hrtime () доступен в Node.js - он возвращает значение в наносекундах

var hrTime = process.hrtime()
console.info(hrTime[0] * 1000000 + hrTime[1] / 1000)

если вы предпочтете преобразовать его в ms e-3, а не в предложенную микросекунду e-6: hrtime[0] * 1000 + hrtime[1] / 1000000 -> да, я лучше также использую var hrtime! :П

cregox 25.03.2017 17:21

Спасибо, Ахим Кёльнер, немного расширил свой ответ:

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.info также потребует времени для выполнения и повлияет на тесты производительности).

Обратите внимание: чтобы измерить время выполнения асинхронных функций, вы должны вставить var timeInMilliseconds = process.hrtime(t0)[1]/1000000; в обратный вызов. Например,

var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;

});

Если вы хотите измерить время между несколькими вещами, которые не вложены, вы можете использовать это:

function timer(lap){ 
    if (lap) console.info(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); 
    timer.prev = performance.now();
}

Подобно console.time (), но проще в использовании, если вам не нужно отслеживать предыдущие таймеры.

Если вам нравится синий цвет из console.time (), вы можете использовать эту строку вместо

console.info(`${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'

Это может вам помочь.

var t0 = date.now(); doSomething(); var t1 = date.now(); console.info("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")

Хотя этот фрагмент кода может решить вопрос, включая объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода. Также постарайтесь не загромождать свой код пояснительными комментариями, это снижает удобочитаемость как кода, так и пояснений!

Filnor 16.03.2018 10:09

Пару месяцев назад я собрал свою собственную процедуру, которая определяет функцию с помощью 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.info(measure.duration)
}

ПРИМЕЧАНИЕ:

Если вы собираетесь использовать объект performance в приложении Node.js, вы должны включить следующее требование: const { performance } = require('perf_hooks')

Думаю, в этом случае performance.mark('end') вам не нужен

kofifus 04.10.2019 01:43

вы также можете использовать оператор добавления здесь

 var start = +new Date();
 callYourFunctionHere();
 var end = +new Date();
 var time = end - start;
 console.info('total execution time = '+ time + 'ms');
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

Вот декоратор для функций времени

let timed = (f) => (...args)=>{
    let start = performance.now();
    let ret = f(...args);
    console.info(`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 (... args), и это должно сработать для них. Ситуация усложняется, если вы хотите, чтобы один декоратор обрабатывал как синхронизирующие, так и асинхронные функции.

Это именно то, что я искал. Спасибо!

Andrew Watters 27.06.2019 20:18

Есть ли способ сделать его универсальным для использования с асинхронными функциями?

TotalAMD 05.01.2020 05:31

Это здорово, есть ли способ заставить его уважать типы Typescript?

Tim Trewartha 14.10.2020 12:07

В моем случае я предпочитаю использовать @grammar 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.info(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.info("delay 1");
        await delay(timout)
        console.info("delay 2");
    }
}

const t = new Test();
t.test(1000)
t.test(100)

.babelrc (для Babel 6)

 {
    "plugins": [
        "transform-decorators-legacy"
    ]
 }

Секундомер с накопительными циклами

Работает с сервером и клиентом (Node или DOM), использует API Performance. Хорошо, когда у вас много маленьких циклов, например. в функции, вызываемой 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.info(`${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];
    }
};

Можно использовать только одну переменную:

var timer = -performance.now();

// Do something

timer += performance.now();
console.info("Time: " + (timer/1000).toFixed(5) + " sec.")

timer/1000 - для преобразования миллисекунд в секунды

.toFixed(5) - для обрезки лишних цифр

Есть несколько способов достичь этой цели:

  1. используя 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');
    
  2. это наиболее эффективный способ: используя performance.now (), например

    var v1 = performance.now();
    //run the function here for which you have top measure the time 
    var v2 = performance.now();
    console.info("total time  taken = "+(v2-v1)+"milliseconds");
    
  3. используйте + (оператор добавления) или 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.info("time === = ", timeTaken);
    

Вот что происходит, когда вы применяете унарный оператор плюса к экземпляру Date: Получить значение рассматриваемого экземпляра Date Преобразуйте его в число

ПРИМЕЧАНИЕ: getTime() дает лучшую производительность, чем унарный оператор +.

Лучше всего использовать модуль 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.info(entry));
  })

  return val;
}

doSomething(4);

Попробуйте здесь

С производительностью

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.info("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');
  1. Для Начало таймер используйте console.time("myTimer");
  2. По желанию: Для Распечатать прошедшего времени используйте console.timeLog("myTimer");
  3. Наконец, к останови таймер и распечатай финальный время: console.timeEnd("myTimer");

Вы можете прочитать об этом больше на MDN и в Документация по Node.js.

Доступно в Chrome, Firefox, Opera и NodeJS. (не в Edge или Internet Explorer).

Другие вопросы по теме