web-dev-qa-db-fra.com

Comment comparer le code JavaScript?

Existe-t-il un package qui m'aide à comparer le code JavaScript? Je ne parle pas de Firebug et de tels outils.

J'ai besoin de comparer 2 fonctions JavaScript différentes que j'ai implémentées. Je connais très bien le module Perl's Benchmark ( Benchmark.pm ) et je recherche quelque chose de similaire en JavaScript.

L'accent mis sur l'analyse comparative du code JavaScript est-il allé trop loin? Puis-je m'en sortir avec le chronométrage d'une seule série de fonctions?

94
Ionic Walrus

Il suffit de chronométrer plusieurs itérations de chaque fonction. Une seule itération ne suffira probablement pas, mais (selon la complexité de vos fonctions) quelque part plus proche de 100 voire 1 000 itérations devrait faire l'affaire.

Firebug a également un profiler si vous voulez voir quelles parties de votre fonction la ralentissent.

Edit: Pour les futurs lecteurs, la réponse ci-dessous recommandant JSPerf devrait être la bonne réponse. Je supprimerais le mien, mais je ne peux pas car il a été sélectionné par l'OP. L'analyse comparative est bien plus qu'une simple exécution de nombreuses itérations, et JSPerf s'en charge pour vous.

33
Sasha Chedygov

jsperf.com est le site de référence pour tester les performances de JS. Commencez par là. Si vous avez besoin d'un cadre pour exécuter vos propres tests à partir de la ligne de commande ou des scripts, utilisez Benchmark.js , la bibliothèque sur laquelle jsperf.com est construit.

Remarque: Quiconque teste du code Javascript devrait se renseigner sur les pièges des "microbenchmarks" (petits tests qui ciblent une fonctionnalité ou une opération spécifique, plutôt que des tests plus complexes basé sur des modèles de code du monde réel). Ces tests peuvent être utiles mais sont sujets à des imprécisions en raison du fonctionnement des runtimes JS modernes. Présentation de Vyacheslav Egorov sur la performance et l'analyse comparative mérite d'être regardé pour avoir une idée de la nature du (des) problème (s).

Edit: Suppression des références à mon travail JSLitmus car il n'est tout simplement plus pertinent ni utile.

113
broofa

Il suffit d'ajouter une minuterie rapide au mélange, que quelqu'un peut trouver utile:

var timer = function(name) {
    var start = new Date();
    return {
        stop: function() {
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        }
    }
};

Idéalement, il serait placé dans une classe, et non utilisé comme un global comme je l'ai fait à des fins d'exemple ci-dessus. Son utilisation serait assez simple:

var t = timer('Some label');
// code to benchmark
t.stop(); // prints the time elapsed to the js console
64
Kenny

Un moyen simple.

console.time('test');
console.timeEnd('test');
32
stadnik0ff

J'utilise cette implémentation simple de la réponse @musicfreaks. Il n'y a pas de fonctionnalités, mais il est vraiment facile à utiliser. Cette bench(function(){return 1/2;}, 10000, [], this) calculera 1/2 10 000 fois.

/**
 * Figure out how long it takes for a method to execute.
 * 
 * @param {Function} method to test 
 * @param {number} iterations number of executions.
 * @param {Array} args to pass in. 
 * @param {T} context the context to call the method in.
 * @return {number} the time it took, in milliseconds to execute.
 */
var bench = function (method, iterations, args, context) {

    var time = 0;
    var timer = function (action) {
        var d = Date.now();
        if (time < 1 || action === 'start') {
            time = d;
            return 0;
        } else if (action === 'stop') {
            var t = d - time;
            time = 0;    
            return t;
        } else {
            return d - time;    
        }
    };

    var result = [];
    var i = 0;
    timer('start');
    while (i < iterations) {
        result.Push(method.apply(context, args));
        i++;
    }

    var execTime = timer('stop');

    if ( typeof console === "object") {
        console.log("Mean execution time was: ", execTime / iterations);
        console.log("Sum execution time was: ", execTime);
        console.log("Result of the method call was:", result[0]);
    }

    return execTime;  
};
19
fncomp

Il est vraiment difficile d'écrire des références décentes pour tous les navigateurs. Le simple fait de chronométrer un nombre prédéfini d'itérations de votre code est pas du tout pare-balles .

Comme @broofa l'a déjà suggéré, consultez jsPerf . Il utilise Benchmark.js dans les coulisses.

8
Mathias Bynens

si vous écrivez un script de référence personnalisé, assurez-vous de noter que certains navigateurs appliquent des manipulations dom uniquement après la fin de la fonction dans laquelle ils sont définis. Plus de détails ici http://www.quirksmode.org/blog/archives/2009/08/when_to_read_ou.html

2
lukins

Si vous avez besoin de quelque chose de simple, vous pouvez faire comme ceci:

'use strict'
console.clear()

const powerOf = x => y => Math.pow(x, y)
const powerOfThree = powerOf(3)

function performanceCalc(fn, ...params) {
    const start = +new Date()
    const result = fn(...params)
    const end = +new Date()

    console.log(`Result: ${result}. Execution Time: ${end - start} ms`)
}

performanceCalc(powerOfThree, 2)

Voici un exemple de code

1
Vlad Bezden