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

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

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

Ответы [ 24 ]

6 голосов
/ 01 февраля 2019

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

var timer = -performance.now();

// Do something

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

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

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

5 голосов
/ 18 сентября 2014

Поскольку 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);
        }
    }
}
5 голосов
/ 16 марта 2018

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

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

4 голосов
/ 18 декабря 2015

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

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;

});
2 голосов
/ 12 сентября 2018

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

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

2 голосов
/ 18 марта 2018

Пару месяцев назад я собрал свою собственную подпрограмму, которая время от времени определяла функцию, используя Date.now () - хотя в то время принятым методом, казалось, был performance.now () - потому что объект производительности еще не доступен (встроен) в стабильном выпуске Node.js.

Сегодня я провел еще какое-то исследование и нашел другой метод определения времени. Так как я также нашел, как использовать это в коде Node.js, я решил поделиться этим здесь.

Следующее объединено с примерами, приведенными w3c и Node.js :

function functionTimer() {
    performance.mark('start')
    functionToBeTimed()
    performance.mark('end')
    performance.measure('Start to End', 'start', 'end')
    const measure = performance.getEntriesByName('Start to End')[0]
    console.log(measure.duration)
}

Примечание:

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

1 голос
/ 29 января 2019

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

Работает с сервером и клиентом (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];
    }
};
1 голос
/ 29 сентября 2018

В моем случае я предпочитаю использовать @gramar 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"
    ]
 }
1 голос
/ 14 августа 2018
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

1 голос
/ 03 апреля 2017

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

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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...