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

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

Я изначально задал этот вопрос еще в 2008 году. Принятый ответ тогда было использовать новая дата().методов gettime() однако теперь мы все можем согласиться что используя стандарт производительность.сейчас() API больше соответствующий. Поэтому я изменяю принятый ответ на этот.

20 ответов


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

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 класс


используя


использовать новая дата().методов 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);

не используйте 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 ++

  • etc, и т. д.

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

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

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


также,никогда не используйте Date на что-нибудь потому что на него влияют изменения в "системном времени". Что означает "мы"!--12-->будет получить недопустимые результаты-например, "отрицательное время" - когда у пользователя нет точного системного времени:

На Октября 2014 Года, мои системные часы вышли из строя и думаю, что.... Я открыл Gmail и увидел все из писем моего дня " отправлено 0 минут назад". И я думал, что Gmail должен быть построен инженерами мирового класса из Google.......

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

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

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


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

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

чтобы профилировать ваш JavaScript:

  • на хром, нажмите клавишу F12 и выберите профили tab, затем соберите профиль процессора JavaScript.
  • на в Firefox установить/открыть 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 andt 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. Есть также несколько polyfills доступен.

еще один вариант измерения времени выполнения в дикой природе -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 доступно (что я и написал).


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


используйте 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]

производительность.сейчас() необязательно-просто передайте false в функцию конструктора секундомера.


чтобы расширить код 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);


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


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

спасибо, Achim Koellner, расширит ваш ответ немного:

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;

});

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

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


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

 var start = +new Date()

 for (i = 0; i < 50000; ++i) {
   // do something
  }

 var end = +new Date()
 var time = end - start;
 console.log('total execution time = '+ time + 'ms');

пару месяцев назад я собрал свою собственную рутину, которая раз функцию с помощью даты.теперь () -- хотя в то время принятый метод, казалось, был performance.сейчас() -- поскольку объект производительности еще не доступен (встроенный) в стабильном узле.освобождение от JS.

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

В следующем сочетании из примеров, приведенных W3C по и узел.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)
}

Примечание:

Если вы намерены использовать


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


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

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

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

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

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'

вот декоратор для функций синхронизации

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 async и добавить await до f(...args), и это должно сработать для них. Это становится более сложным, если вы хотите, чтобы один декоратор обрабатывал как функции синхронизации, так и асинхронные.


в моем случае я использую @ 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.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"
    ]
 }

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

//=-=|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% от размера gzipped (53.83% без gzip

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

поскольку 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); 

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

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