web-dev-qa-db-fra.com

Comment mesurer le temps mis par une fonction à exécuter

Je dois obtenir le temps d'exécution en millisecondes.

À l'origine, j'avais posé cette question en 2008. La réponse acceptée puis était d'utiliser new Date (). getTime () Cependant, nous pouvons tous être d'accord maintenant que l’utilisation de la norme performance.now () API est supérieure à approprié. Je change donc la réponse acceptée à celle-ci.

872
Julius A

Utiliser 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: il est nécessaire de importer la performance class


Utiliser console.time(non standard)} _ ( niveau de vie )

console.time('someFunction');

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

console.timeEnd('someFunction');

Remarque: 
La chaîne passée aux méthodes time() et timeEnd() doit correspondre
(pour le chronomètre doit se terminer comme prévu).

console.time() documentations:

  1. Documentation NodeJS concernant
  2. Documentation MDN (côté client)
1331
vsync

utilisez new Date (). getTime ()

La méthode getTime () renvoie le nombre de millisecondes écoulées depuis le 1er janvier 1970 à minuit.

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

N'utilisez pas Date (). Lire ci-dessous.

Utilisez performance.now():

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

Cela fonctionne sur:

  • IE 10 ++

  • FireFox 15 ++

  • Chrome 24 ++

  • Safari 8 ++

  • Opera 15 ++

  • Android 4.4 ++

  • etc, etc

console.time peut être viable pour vous , mais c'est non standard § :

Cette fonctionnalité n'est pas standard et ne fait pas partie des standards. Ne l'utilisez pas sur les sites de production faisant face au Web: cela ne fonctionnera pas pour tous les utilisateurs. There peut aussi avoir de grandes incompatibilités entre les implémentations et le comportement peut changer dans le futur.

Outre le support du navigateur, performance.now semble avoir le potentiel de fournir des timings plus précis car il semble s'agir de la version complète de console.time.


<rant> De plus, NE JAMAIS utiliser Date pour rien car il est affecté par les modifications de "l'heure système" ". Ce qui signifie que nous == obtiendrons des résultats non valides, comme un "timing négatif" - lorsque l'utilisateur ne dispose pas d'une heure système précise:

En octobre 2014, mon horloge système est tombée en panne et devinez quoi .... J'ai ouvert Gmail et j'ai vu tous des courriels de ma journée "envoyé il y a 0 minutes ". Et je pensais que Gmail devait être construit par des ingénieurs de classe mondiale de Google .......

(Réglez l'horloge de votre système sur il y a un an et accédez à Gmail pour que nous puissions tous bien rire. Peut-être qu'un jour nous aurons un Hall of Shame pour JS Date.)

La fonction now() de Google Spreadsheet souffre également de ce problème.

La seule fois où vous utiliserez Date, c’est lorsque vous souhaitez afficher l’utilisateur his heure de l’horloge système. Pas quand vous voulez obtenir le temps ou mesurer quoi que ce soit.

396
Pacerier

Si vous devez obtenir le temps d'exécution de la fonction sur votre ordinateur de développement local, vous pouvez utiliser les outils de profilage de votre navigateur ou des commandes de console telles que console.time() et console.timeEnd() .

Tous les navigateurs modernes ont des profileurs JavaScript intégrés. Ces profileurs doivent fournir la mesure la plus précise possible, car vous n'avez pas à modifier votre code existant, ce qui pourrait affecter le temps d'exécution de la fonction.

Pour profiler votre JavaScript:

  • Dans Chrome, appuyez sur F12 et sélectionnez l'onglet Profils, puis Collecter le profil de la CPU JavaScript.
  • Dans Firefox, installez/ouvrez Firebug et cliquez sur le bouton Profil
  • Dans IE 9+, appuyez sur F12, cliquez sur Script ou Profiler (selon votre version d'Internet Explorer).

Sinon, sur votre machine de développement, vous pouvez ajouter une instrumentation à votre code avec console.time() et console.timeEnd() . Ces fonctions, prises en charge par Firefox11 +, Chrome2 + et IE11 +, signalent les minuteries que vous démarrez/arrêtez via console.time(). time() prend un nom de minuterie défini par l'utilisateur en tant qu'argument, et timeEnd() indique ensuite le temps d'exécution depuis le démarrage de la minuterie:

function a() {
  console.time("mytimer");
  ... do stuff ...
  var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF
}

Notez que seul Firefox renvoie le temps écoulé dans l'appel timeEnd(). Les autres navigateurs signalent simplement le résultat à la console du développeur: la valeur de retour de timeEnd() est indéfinie.

Si vous voulez obtenir le temps d'exécution de la fonction dans la nature, vous devrez instrumenter votre code. Vous avez plusieurs options. Vous pouvez simplement enregistrer les heures de début et de fin en interrogeant new Date().getTime():

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

Cependant, l'objet Date n'a qu'une résolution en millisecondes et sera affecté par les modifications d'horloge système du système d'exploitation. Dans les navigateurs modernes, il existe une meilleure option.

La meilleure option consiste à utiliser le temps de haute résolution , également appelé window.performance.now(). now() est meilleur que le Date.getTime() traditionnel de deux manières importantes:

  1. now() est un double avec une résolution inférieure à la milliseconde qui représente le nombre de millisecondes depuis le début de la navigation dans la page. Il renvoie le nombre de microsecondes dans la fraction (par exemple, une valeur de 1000,123 correspond à 1 seconde et à 123 microsecondes).

  2. now() est en augmentation monotone. Ceci est important car Date.getTime() peut éventuellement sauter en avant ou même en arrière lors d'appels suivants. Notamment, si l'heure système du système d'exploitation est mise à jour (par exemple, la synchronisation d'horloge atomique), Date.getTime() est également mis à jour. Il est garanti que now() sera toujours en augmentation monotone, il n'est donc pas affecté par l'heure système du système d'exploitation - ce sera toujours l'heure murale (en supposant que votre horloge murale n'est pas atomique ...).

now() peut être utilisé dans presque tous les endroits où new Date().getTime(), + new Date ett Date.now() sont. La seule exception est que les temps Date et now() ne se mélangent pas, car Date est basé sur unix-Epoch (le nombre de millisecondes depuis 1970), alors que now() est le nombre de millisecondes écoulées depuis le début de la navigation dans votre page (donc il sera beaucoup plus petit que Date).

Voici un exemple d'utilisation de now():

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

now() est pris en charge par Chrome stable, Firefox 15+ et IE10. Plusieurs polyfills sont également disponibles.

Une autre option pour mesurer le temps d'exécution dans la nature est UserTiming. UserTiming se comporte de la même façon que console.time() et console.timeEnd(), mais il utilise le même horodatage haute résolution que now() (vous obtenez ainsi une horloge augmentant de manière monotone de moins d'une milliseconde) et enregistre l'horodatage et la durée du PerformanceTimeline .

UserTiming a les concepts de marques (horodatages) et mesures (durées). Vous pouvez définir autant de choix que vous le souhaitez et ils sont exposés sur le PerformanceTimeline .

Pour enregistrer un horodatage, appelez mark(startMarkName). Pour obtenir la durée depuis votre première marque, vous appelez simplement measure(measurename, startMarkname). La durée est ensuite enregistrée dans PerformanceTimeline à côté de vos marques.

function a() {
  window.performance.mark("start");
  ... do stuff ...
  window.performance.measure("myfunctionduration", "start");
}

// duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];

UserTiming est disponible dans IE10 + et Chrome25 +. Il y a aussi un polyfill disponible (que j'ai écrit).

50
NicJ

Pour obtenir des valeurs précises, vous devez utiliser Interface de performance . Il est pris en charge dans les versions modernes de Firefox, Chrome, Opera et IE. Voici un exemple de la façon dont il peut être utilisé:

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

Date.getTime() ou console.time() ne convient pas pour mesurer un temps d'exécution précis. Vous pouvez les utiliser si une estimation approximative rapide vous convient. Par estimation approximative, je veux dire que vous pouvez obtenir un décalage de 15 à 60 ms par rapport au temps réel.

Vérifiez ce brillant post sur la mesure du temps d'exécution en JavaScript. L'auteur donne également quelques liens sur l'exactitude du temps JavaScript, qui méritent d'être lus. 

31
Varvara Kalinina

Utilisez Firebug, activez la console et Javascript. Cliquez sur le profil. Recharger. Cliquez à nouveau sur le profil. Voir le rapport.

18
Stefan Mai
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]');
};

Référence

var stopwatch = new StopWatch();
stopwatch.start();

for (var index = 0; index < 100; index++) {
    stopwatch.printElapsed('Instance[' + index + ']');
}

stopwatch.stop();

stopwatch.printElapsed();

Sortie

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 () est facultatif - il suffit de passer false dans la fonction constructeur StopWatch.

11
kayz1

process.hrtime () est disponible dans Node.js - il renvoie une valeur en nanosecondes.

var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
11
Achim Koellner

Pour étendre davantage le code de vsync afin d’avoir la possibilité de renvoyer timeEnd en tant que valeur dans NodeJS, utilisez ce petit morceau de code.

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

Maintenant, utilisez le code comme suit:

console.time('someFunction timer');

someFunction();

var executionTime = console.timeEndValue('someFunction timer');
console.log("The execution time is " + executionTime);


Cela vous donne plus de possibilités. Vous pouvez stocker le temps d'exécution à utiliser à d'autres fins, comme l'utiliser dans des équations, ou stocké dans une base de données, envoyé à un client distant via des websockets, servi sur une page Web, etc.

8
Levi Roberts

vous pouvez également utiliser l'opérateur add ici

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

Cela peut vous aider.

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

5
Wajeeh Aslam

Étant donné que console.time et performance.now ne sont pas pris en charge par certains navigateurs principaux (IE10), j'ai créé un utilitaire mince qui utilise les meilleures méthodes disponibles. Cependant, il manque la gestion des erreurs pour les utilisations fausses (appel à End() sur un minuteur non initialisé).

Utilisez-le et améliorez-le à votre guise. 

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
Mx.

Merci, Achim Koellner, développera un peu votre réponse:

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

Notez que vous ne devez rien faire d'autre que ce que vous souhaitez mesurer (par exemple, console.log prendra également du temps à s'exécuter et aura une incidence sur les tests de performance).

Notez que, pour mesurer l'heure d'exécution des fonctions asynchrones, vous devez insérer var timeInMilliseconds = process.hrtime(t0)[1]/1000000; dans le rappel. Par exemple,

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

});
4
Andrew Marin

Voici un décorateur pour les fonctions de chronométrage

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

Usage:

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' 

Si vous utilisez des fonctions asynchrones, vous pouvez rendre timed async et ajouter await before f (... args), et cela devrait fonctionner pour ceux-ci. Cela devient plus compliqué si vous voulez qu'un décorateur gère les fonctions de synchronisation et async. 

2
aljgom

Il est possible d'utiliser une seule variable:

var timer = -performance.now();

// Do something

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

timer/1000 - convertir les millisecondes en secondes

.toFixed(5) - pour couper les chiffres supplémentaires

2
user1032559

Il y a quelques mois, j'ai mis en place ma propre routine qui chronomètre une fonction à l'aide de Date.now () - bien qu'à l'époque la méthode acceptée semblait être performance.now () -- parce que l'objet de performance n'est pas encore disponible (intégré) dans la version stable Node.js.

Aujourd'hui, je faisais quelques recherches supplémentaires et j'ai trouvé une autre méthode de chronométrage. Depuis que j'ai aussi trouvé comment utiliser ceci dans le code Node.js, j'ai pensé le partager ici. 

Les exemples suivants sont combinés à partir des exemples donnés par w3c et 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)
}

REMARQUE:

Si vous avez l'intention d'utiliser l'objet performance dans une application Node.js, vous devez inclure l'exigence suivante: const { performance } = require('perf_hooks')

2
Jonathan Chasteen

Si vous voulez mesurer le temps entre plusieurs choses qui ne sont pas imbriquées, vous pouvez utiliser ceci:

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

Similaire à console.time (), mais utilisation plus facile si vous n'avez pas besoin de garder la trace des timers précédents.

Si vous aimez la couleur bleue de console.time (), vous pouvez utiliser cette ligne à la place

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'
1
aljgom

Dans mon cas, je préfère utiliser @ grammar suger et le compiler avec Babel.
Le problème de cette méthode est que la fonction doit être à l'intérieur de l'objet. 

Exemple de code 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 (pour babel 6)

 {
    "plugins": [
        "transform-decorators-legacy"
    ]
 }
1
Yu Huang
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
0
Homam Bahrani

Avec performance

NodeJs: Il est nécessaire d'importer la classe de performance.

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

Utilisation de console.time

console.time('someFunction');

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

console.timeEnd('someFunction');
0
Chandraprakash

Chronomètre avec cycles cumulatifs

Fonctionne avec serveur et client (nœud ou DOM), utilise l'API Performance. Bon lorsque vous avez beaucoup de petits cycles, par ex. dans une fonction appelée 1000 fois qui traite 1000 objets de données mais vous voulez voir comment chaque opération de cette fonction est ajoutée au total.

Donc, celui-ci utilise un module global (singleton) timer. Identique à un modèle de classe singleton, un peu plus simple à utiliser, mais vous devez le mettre dans un exemple séparé. stopwatch.js fichier.

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];
    }
};
0
gombosg

Le meilleur moyen serait d'utiliser le module performance hooks. Bien qu'instable, vous pouvez mark des zones spécifiques de votre code et measure le duration entre les zones marquées.

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

Essayez ici

0
toondaey

il y a plusieurs façons d'atteindre cet objectif:

  1. en utilisant 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. c'est le moyen le plus efficace: en utilisant performance.now ()

ex. 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. utilisez + (add operator) ou 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);

Voici ce qui se passe lorsque vous appliquez l'opérateur unaire plus à une instance de date: Récupération de la valeur de l'instance de date en question

REMARQUE: getTime () offre de meilleures performances que l'opérateur unaire +.

0
Rohit