¿Cómo puedo comparar el código JavaScript? [cerrado]

104

¿Existe un paquete que me ayude a comparar el código JavaScript? No me refiero a Firebug y esas herramientas.

Necesito comparar 2 funciones de JavaScript diferentes que he implementado. Estoy muy familiarizado con el módulo Benchmark ( Benchmark.pm ) de Perl y estoy buscando algo similar en JavaScript.

¿Se ha exagerado el énfasis en la evaluación comparativa del código JavaScript? ¿Puedo cronometrar solo una ejecución de las funciones?

Morsa iónica
fuente
Parece ser un dup: stackoverflow.com/search?q=javascript+profiler
steamer25
Sé que no es a prueba de balas y todo, pero está relacionado de todos modos: a veces solo quieres saber cómo medir el tiempo que tarda una función en ejecutarse .
Skippy le Grand Gourou
1
Me buena herramienta de referencia JavaScript puede encontrar aquí: jsben.ch
EscapeNetscape

Respuestas:

36

Solo calcula varias iteraciones de cada función. Una iteración probablemente no sea suficiente, pero (dependiendo de qué tan complejas sean sus funciones) un lugar más cercano a 100 o incluso 1,000 iteraciones debería hacer el trabajo.

Firebug también tiene un generador de perfiles si desea ver qué partes de su función la están ralentizando.

Editar: Para los futuros lectores, la siguiente respuesta que recomienda JSPerf debería ser la respuesta correcta. Eliminaría el mío, pero no puedo porque ha sido seleccionado por el OP. La evaluación comparativa implica mucho más que simplemente ejecutar muchas iteraciones, y JSPerf se encarga de eso por usted.

Sasha Chedygov
fuente
12
Simplemente cronometrar un número predefinido de iteraciones de su código no es en absoluto infalible . Además, tener Firebug abierto desactiva el compilador Just-In-Time (JIT) de Firefox, lo que significa que las pruebas se ejecutarán en el intérprete, es decir, mucho más lento de lo que lo harían de otra manera. Usar el generador de perfiles de Firebug no le dará los resultados esperados.
Mathias Bynens
1
@Mathias: Bueno, para ser justos, esta respuesta es muy antigua.
Sasha Chedygov
2
Seguro, no te ofendas amigo. Solo pensé en comentar para referencia futura ahora que se han realizado más investigaciones sobre el tema.
Mathias Bynens
4
O use jsben.ch ya que jsperf está inactivo
EscapeNetscape
118

jsperf.com es el sitio de referencia para probar el rendimiento de JS. Empiece por ahí. Si necesita un marco para ejecutar sus propias pruebas desde la línea de comandos o scripts, use Benchmark.js , la biblioteca sobre la que está construido jsperf.com.

Nota: Cualquiera que pruebe código Javascript debe informarse sobre las trampas de los "microbenchmarks" (pequeñas pruebas que apuntan a una función u operación específica, en lugar de pruebas más complejas basadas en patrones de código del mundo real). Estas pruebas pueden ser útiles, pero son propensas a la inexactitud debido a cómo funcionan los tiempos de ejecución de JS modernos. Vale la pena ver la presentación de Vyacheslav Egorov sobre desempeño y evaluación comparativa para tener una idea de la naturaleza de los problemas.

Editar: Se eliminaron las referencias a mi trabajo de JSLitmus porque ya no es relevante ni útil.

broofa
fuente
3
Actualización: solo use jsperf.com, ha mejorado mucho y funciona muy bien para este tipo de cosas. jslitmus todavía funciona, pero no se ha desarrollado activamente durante bastante tiempo.
broofa
Esta es la respuesta superior. +1
Justin Force
1
Quería usar jsperf, pero parece estar contando cuántas veces puede ejecutar el código durante un período de tiempo, en lugar de cronometrar la llamada real para N bucles. Ojalá tuvieran una opción para elegir.
Jeach
1
@Jeach - jsperf da "operaciones / segundo". Simplemente multiplique ese valor por el tiempo (en segundos) durante el que se ejecutará el código.
broofa
4
Actualización: jsperf ya no está en línea y no se sabe cuándo volverá a estar en línea. Consulte este hilo de github para obtener más información.
James Gould
74

Simplemente agregando un temporizador rápido a la mezcla, que alguien puede encontrar útil:

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

Idealmente, se colocaría en una clase y no se usaría como global como lo hice para los propósitos de ejemplo anteriores. Usarlo sería bastante simple:

var t = timer('Some label');
// code to benchmark
t.stop(); // prints the time elapsed to the js console
Kenny
fuente
6
Buen uso de cierres aquí.
Dandy
12
Para obtener un resultado más preciso, es posible que desee utilizar en performance.now()lugar de Date() developer.mozilla.org/en-US/docs/Web/API/Performance/now
thormeier
Justo lo que necesitaba - un timeIt ()
Gishu
1
Versión de TypeScript: pastebin.com/gCs9CB5F
Alexander Taylor
1
Para node.js, puede usar process.hrtime () para obtener una resolución de nanosegundos.
Xeoncross
56

De forma sencilla.

console.time('test');
console.timeEnd('test');
stadnik0ff
fuente
3
Esta debería ser la respuesta aceptada. El uso de un servicio de terceros a veces no es conveniente, y el simple hecho de usar una función incorporada es excelente.
Brainbag
1
@brainbag: la pregunta era sobre la evaluación comparativa, que implica más que simplemente medir cuánto tiempo se ejecuta un fragmento de código. Además, los temporizadores de consola solo son útiles si el código en cuestión tarda más de 1 milisegundo (el límite de su resolución).
broofa
Es posible que también desee ejecutar su punto de referencia en un conjunto de pruebas, lo que requiere tener acceso al valor del temporizador.
JamesDev
20

He estado usando esta implementación simple de la respuesta de @musicfreaks. No tiene funciones, pero es muy fácil de usar. Esto bench(function(){return 1/2;}, 10000, [], this)calculará 1/2 10,000 veces.

/**
 * 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;  
};
fncomp
fuente
9

Es realmente difícil escribir puntos de referencia decentes entre navegadores. Simplemente cronometrar un número predefinido de iteraciones de su código no es en absoluto infalible .

Como ya sugirió @broofa, consulte jsPerf . Utiliza Benchmark.js detrás de escena.

Mathias Bynens
fuente
1

Si necesita algo simple, puede hacer esto:

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

Aquí hay un ejemplo del código.

Vlad Bezden
fuente
Simple fue definitivamente la mejor opción en mi caso ... escribir algunas pruebas para comparar los tiempos de respuesta para API (sin necesidad de tiempos extremadamente precisos).
kashiraja