Как измерить время выполнения функции - PullRequest
946 голосов
/ 24 ноября 2008

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

Я изначально задавал этот вопрос еще в 2008 году. Принятый ответ тогда нужно было использовать new Date (). getTime () Однако мы все можем сейчас согласиться что использование стандартного performance.now () API более подходящее. Поэтому я меняю принятый ответ на этот.

Ответы [ 24 ]

1420 голосов
/ 29 декабря 2009

Использование 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 : (нестандартное) ( стандарт жизни )

console.time('someFunction');

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

console.timeEnd('someFunction');

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

console.time() документация:

  1. Документация NodeJS относительно
  2. Документация MDN (на стороне клиента)
604 голосов
/ 24 ноября 2008

использовать новая дата (). 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);
389 голосов
/ 26 марта 2013

Не используйте дату (). Читайте ниже.

Использование performance.now():

<script>
var a = performance.now();
alert('do something...');
var b = performance.now();
alert('It took ' + (b - a) + ' ms.');
</script>

Работает на:

console.time может быть жизнеспособным для вас , но это нестандартно & sect; :

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

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


Кроме того, НИКОГДА не используйте Date для чего-либо , поскольку на него влияют изменения "системного времени". Это означает, что мы получим недопустимые результаты & mdash; например, "отрицательное время" & mdash; когда у пользователя нет точного системного времени:

В октябре 2014 года мои системные часы перестали работать и угадайте, что .... Я открыл Gmail и увидел всех писем за день, отправленных 0 минут назад ». И я думал, что Gmail должен быть создан инженерами мирового класса из Google .......

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

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

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

50 голосов
/ 14 января 2014

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

Если вы хотите получить время выполнения функции в диком виде , вам придется обрабатывать свой код. У вас есть пара вариантов. Вы можете просто сохранить время начала и окончания, запросив new Date().getTime():

function a() {
  var start = new Date().getTime();
  ... do stuff ...
  var end = new Date().getTime();
  var dur = end - start;
}

Однако объект Date имеет разрешение только в миллисекундах и будет зависеть от изменений системных часов любой ОС. В современных браузерах есть лучший вариант.

Лучшим вариантом является использование High Resolution Time , он же 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-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 (который я написал).

32 голосов
/ 26 февраля 2015

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

18 голосов
/ 24 ноября 2008

Используйте Firebug, включите и консоль, и Javascript. Нажмите Профиль. Обновить. Нажмите Профиль еще раз. Посмотреть отчет.

11 голосов
/ 11 марта 2015

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

var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
11 голосов
/ 08 августа 2013
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 () необязательно - просто передайте false в функцию конструктора StopWatch.

8 голосов
/ 04 августа 2013

Для дальнейшего расширения кода 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);


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

7 голосов
/ 02 июля 2018

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

 var start = +new Date();
 callYourFunctionHere();
 var end = +new Date();
 var time = end - start;
 console.log('total execution time = '+ time + 'ms');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...