web-dev-qa-db-fra.com

Comment mesurer le temps d'exécution du code javascript avec des rappels

J'ai un morceau de code javascript que j'exécute à l'aide de l'interpréteur node.js.

for(var i = 1; i < LIMIT; i++){
    db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
          if( err || !saved ) console.log("Error");
          else console.log("Saved");
    });
}

Je veux savoir comment mesurer le temps pris par ces opérations d'insertion de base de données. Je pourrais calculer la différence entre les valeurs de Date après et avant ce morceau de code, mais ce serait incorrect en raison de la nature asynchrone du code.

290
Stormshadow

Utilisez les Node.js console.time() et console.timeEnd() :

var i;
console.time("dbsave");

for(i = 1; i < LIMIT; i++){
    db.users.save({id : i, name : "MongoUser [" + i + "]"}, end);
}

end = function(err, saved) {
    console.log(( err || !saved )?"Error":"Saved");
    if(--i === 1){console.timeEnd("dbsave");}
};
657
user2362662

Il existe une méthode conçue pour cela. Départ process.hrtime (); .

Donc, je mets essentiellement cela au sommet de mon application.

var start = process.hrtime();

var elapsed_time = function(note){
    var precision = 3; // 3 decimal places
    var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
    console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time
    start = process.hrtime(); // reset the timer
}

Ensuite, je l'utilise pour voir combien de temps les fonctions prennent. Voici un exemple de base qui imprime le contenu d'un fichier texte appelé "output.txt":

var debug = true;
http.createServer(function(request, response) {

    if(debug) console.log("----------------------------------");
    if(debug) elapsed_time("recieved request");

    var send_html = function(err, contents) {
        if(debug) elapsed_time("start send_html()");
        response.writeHead(200, {'Content-Type': 'text/html' } );
        response.end(contents);
        if(debug) elapsed_time("end send_html()");
    }

    if(debug) elapsed_time("start readFile()");
    fs.readFile('output.txt', send_html);
    if(debug) elapsed_time("end readFile()");

}).listen(8080);

Voici un test rapide que vous pouvez exécuter dans un terminal (BASH Shell):

for i in {1..100}; do echo $i; curl http://localhost:8080/; done
191
D.Deriso

Invoquer console.time('label') enregistrera l'heure actuelle en millisecondes, puis l'appel ultérieur de console.timeEnd('label') affichera la durée à partir de ce point.

Le temps en millisecondes sera automatiquement imprimé à côté de l'étiquette. Vous n'avez donc pas à appeler séparément console.log pour imprimer une étiquette:

console.time('test');
//some code
console.timeEnd('test'); //Prints something like that-> test: 11374.004ms

Pour plus d'informations, reportez-vous à la section Documents de développement de Mozilla sur console.time .

62
jfcorugedo

Pour tous ceux qui souhaitent obtenir une valeur de temps écoulé au lieu d'une sortie de console:

utilisez process.hrtime () comme suggestion @ D.Deriso, voici mon approche la plus simple:

function functionToBeMeasured() {
    var startTime = process.hrtime();
    // do some task...
    // ......
    var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime));
    console.log('It takes ' + elapsedSeconds + 'seconds');
}

function parseHrtimeToSeconds(hrtime) {
    var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
    return seconds;
}
17
Sing

Surpris, personne n'avait encore mentionné les nouvelles bibliothèques intégrées:

Disponible dans Node> = 8.5, et devrait l'être dans Modern Browers

https://developer.mozilla.org/en-US/docs/Web/API/Performance

https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#

Nœud 8.5 ~ 9.x (Firefox, Chrome)

// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
  await delay(1000);
}
performance.mark('A');
(async ()=>{
  await doSomeLongRunningProcess();
  performance.mark('B');
  performance.measure('A to B', 'A', 'B');
  const measure = performance.getEntriesByName('A to B')[0];
  // firefox appears to only show second precision.
  console.log(measure.duration);
  performance.clearMeasures(); // apparently you should remove entries...
  // Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();

https://repl.it/@CodyGeisler/NodeJsPerformanceHooks

Noeud 10.x

https://nodejs.org/docs/latest-v10.x/api/perf_hooks.html

const { PerformanceObserver, performance } = require('perf_hooks');
const delay = time => new Promise(res => setTimeout(res, time))
async function doSomeLongRunningProcess() {
    await delay(1000);
}
const obs = new PerformanceObserver((items) => {
    console.log('PerformanceObserver A to B',items.getEntries()[0].duration);
    performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });

performance.mark('A');

(async function main(){
    try{
        await performance.timerify(doSomeLongRunningProcess)();
        performance.mark('B');
        performance.measure('A to B', 'A', 'B');
    }catch(e){
        console.log('main() error',e);
    }
})();
16
Cody G
var start = +new Date();
var counter = 0;
for(var i = 1; i < LIMIT; i++){
    ++counter;
    db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
          if( err || !saved ) console.log("Error");
          else console.log("Saved");
          if (--counter === 0) 
          {
              var end = +new Date();
              console.log("all users saved in " + (end-start) + " milliseconds");
          }
    });
}
16
Andrey Sidorov

Ancienne question, mais pour une API simple et une solution légère; vous pouvez utiliser perfy qui utilise le temps réel haute résolution (process.hrtime) en interne.

var perfy = require('perfy');

function end(label) {
    return function (err, saved) {
        console.log(err ? 'Error' : 'Saved'); 
        console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds
    };
}

for (var i = 1; i < LIMIT; i++) {
    var label = 'db-save-' + i;
    perfy.start(label); // <——— start and mark time
    db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label));
}

Notez que chaque fois que perfy.end(label) est appelée, cette instance est automatiquement détruite.

Divulgation: a écrit ce module, inspiré par réponse de D.Deriso . Docs ici .

9
Onur Yıldırım

Vous pouvez essayer Benchmark.js . Il supporte de nombreuses plates-formes parmi lesquelles également node.js.

2
jsbeckr

Vous pouvez également essayer exectimer . Il vous donne des commentaires comme:

var t = require("exectimer");

var myFunction() {
   var tick = new t.tick("myFunction");
   tick.start();
   // do some processing and end this tick
   tick.stop();
}

// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.myFunction.min()); // minimal tick duration
console.log(t.timers.myFunction.max()); // maximal tick duration
console.log(t.timers.myFunction.mean()); // mean tick duration
console.log(t.timers.myFunction.median()); // median tick duration

[edit] Il existe même un moyen plus simple d'utiliser exectimer car il peut maintenant envelopper le code à mesurer. Votre code pourrait être emballé comme ceci:

var t = require('exectimer'),
Tick = t.Tick;

for(var i = 1; i < LIMIT; i++){
    Tick.wrap(function saveUsers(done) {
        db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
            if( err || !saved ) console.log("Error");
            else console.log("Saved");
            done();
        });
    });
}

// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.saveUsers.min()); // minimal tick duration
console.log(t.timers.saveUsers.max()); // maximal tick duration
console.log(t.timers.saveUsers.mean()); // mean tick duration
console.log(t.timers.saveUsers.median()); // median tick duration
2
Alexandru Savin

J'ai eu le même problème en passant d'AWS à Azure

Pour express & aws, vous pouvez déjà utiliser, time existant () et timeEnd ()

Pour Azure, utilisez ceci: https://github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_Azure_aws.js

Ces time () et timeEnd () utilisent la fonction existante hrtime (), qui donne un temps réel haute résolution.

J'espère que cela t'aides.

1

Et une autre option consiste à utiliser l'outil express-debug :

express-debug est un outil de développement pour express. C'est un middleware simple qui injecte une sortie de débogage utile dans votre code HTML, de manière non obstructive.

Il offre commodément un panneau de profilage:

temps total de traitement des demandes. middleware, param et timings de route.

Aussi. pour ajouter aux réponses ci-dessus, vous pouvez vérifier cette réponse pour activer tout code de profilage uniquement pour l'environnement de développement.

0
Wtower

Je recommanderais d'essayer NodeTime , ce qui semble bien correspondre à ce que vous essayez de faire.

0
Julian Knight