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

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

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

Ответ 1

Использование 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: 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() Документация:

  1. Документация NodeJS относительно
  2. 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

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

  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.log("total time taken = "+(v2-v1)+"milliseconds";

  1. используйте + (добавить оператор) или 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