Como posso comparar o código JavaScript? [fechadas]

104

Existe um pacote que me ajuda a comparar o código JavaScript? Não estou me referindo ao Firebug e essas ferramentas.

Preciso comparar 2 funções JavaScript diferentes que implementei. Estou muito familiarizado com o módulo Benchmark ( Benchmark.pm ) do Perl e estou procurando algo semelhante em JavaScript.

A ênfase no benchmarking do código JavaScript extrapolou os limites? Posso me safar de cronometrar apenas uma execução das funções?

Morsa iônica
fonte
Parece ser um dup: stackoverflow.com/search?q=javascript+profiler
steamer25
Possível duplicata de Como você testa o desempenho do código JavaScript?
John Slegers
Eu sei que não é à prova de balas e tudo, mas relacionado de qualquer maneira: às vezes você só quer saber como medir o tempo gasto por uma função para executar .
Skippy le Grand Gourou
1
Uma boa ferramenta de benchmark de JavaScript que você pode encontrar aqui: jsben.ch
EscapeNetscape

Respostas:

36

Tempo várias iterações de cada função. Uma iteração provavelmente não será suficiente, mas (dependendo de quão complexas são as suas funções) algo próximo a 100 ou mesmo 1.000 iterações deve fazer o trabalho.

O Firebug também tem um criador de perfil se você quiser ver quais partes de sua função estão tornando-o mais lento.

Edit: Para futuros leitores, a resposta abaixo recomendando JSPerf deve ser a resposta correta. Gostaria de deletar o meu, mas não posso porque foi selecionado pelo OP. O benchmarking envolve muito mais do que apenas executar várias iterações, e o JSPerf cuida disso para você.

Sasha Chedygov
fonte
12
Simplesmente cronometrar um número predefinido de iterações de seu código não é à prova de balas . Além disso, ter o Firebug aberto desativa o compilador Just-In-Time (JIT) do Firefox, o que significa que os testes serão executados no interpretador, ou seja, muito mais lento do que de outra forma. Usar o criador de perfil do Firebug não fornecerá os resultados esperados.
Mathias Bynens
1
@Mathias: Bem, para ser justo, essa resposta é muito antiga.
Sasha Chedygov
2
Claro, sem ofensa, companheiro. Só pensei em comentar para referência futura, agora que mais pesquisas foram feitas sobre o assunto.
Mathias Bynens
4
Ou use jsben.ch, pois jsperf está fora do ar
EscapeNetscape
118

jsperf.com é o site para teste de desempenho de JS. Comece por aí. Se você precisa de uma estrutura para executar seus próprios testes a partir da linha de comando ou scripts, use Benchmark.js , a biblioteca na qual jsperf.com foi construído.

Observação: qualquer pessoa que esteja testando o código Javascript deve se educar sobre as armadilhas dos "microbenchmarks" (pequenos testes que visam um recurso ou operação específica, em vez de testes mais complexos baseados em padrões de código do mundo real). Esses testes podem ser úteis, mas estão sujeitos a imprecisões devido à forma como os tempos de execução JS modernos operam. Vale a pena assistir à apresentação de Vyacheslav Egorov sobre desempenho e benchmarking para ter uma ideia da natureza do (s) problema (s).

Edit: Removidas referências ao meu trabalho JSLitmus, pois não é mais relevante ou útil.

broofa
fonte
3
Atualização: basta usar jsperf.com - ficou muito melhor e funciona muito bem para esse tipo de coisa. jslitmus ainda funciona, mas não foi desenvolvido ativamente por algum tempo.
broofa
Esta é a resposta superior. +1
Justin Force
1
Eu queria usar jsperf, mas parece estar contando quantas vezes ele pode executar o código por um período de tempo, em vez de cronometrar a chamada real para N loops. Eu gostaria que eles tivessem uma opção de escolha.
Jeach
1
@Jeach - jsperf fornece "operações / segundo". Basta multiplicar esse valor pelo tempo (em segundos) para o qual seu código será executado.
Broofa
4
Atualização: jsperf não está mais online, e não há notícias de quando estará online novamente. Veja este tópico do github para mais informações.
James Gould
73

Basta adicionar um temporizador rápido à mistura, que alguém pode achar ú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, ele seria colocado em uma classe e não usado como um global como fiz para os exemplos acima. Usar seria muito simples:

var t = timer('Some label');
// code to benchmark
t.stop(); // prints the time elapsed to the js console
Kenny
fonte
6
Bom uso de fechamentos aqui.
Dandy
12
Para um resultado mais preciso, pode-se usar em performance.now()vez de Date() developer.mozilla.org/en-US/docs/Web/API/Performance/now
thormeier
Exatamente o que eu precisava - um timeIt ()
Gishu
1
Versão TypeScript: pastebin.com/gCs9CB5F
Alexander Taylor
1
Para node.js, você pode usar process.hrtime () para obter resolução de nanossegundos.
Xeoncross
56

Maneira simples.

console.time('test');
console.timeEnd('test');
stadnik0ff
fonte
3
Esta deve ser a resposta aceita. Usar um serviço de terceiros às vezes não é conveniente e apenas usar um recurso integrado simples é excelente.
Brainbag de
1
@brainbag - A questão era sobre benchmarking, que envolve mais do que simplesmente cronometrar por quanto tempo um trecho de código é executado. Além disso, os temporizadores do console são úteis apenas se o código em questão levar mais de 1 milissegundo (o limite de sua resolução).
broofa de
Você também pode executar seu benchmark em um conjunto de testes, que exige acesso ao valor do cronômetro.
JamesDev
20

Tenho usado esta implementação simples da resposta @musicfreaks. Não há recursos, mas é muito fácil de usar. Isso bench(function(){return 1/2;}, 10000, [], this)calculará 1/2 10.000 vezes.

/**
 * 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
fonte
9

É realmente difícil escrever benchmarks decentes entre navegadores. Simplesmente cronometrar um número predefinido de iterações de seu código não é à prova de balas .

Como @broofa já sugeriu, verifique jsPerf . Ele usa Benchmark.js nos bastidores.

Mathias Bynens
fonte
1

Se você precisa de algo simples, pode fazer assim:

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

Aqui está um exemplo do código

Vlad Bezden
fonte
Simples foi definitivamente a melhor opção no meu caso ... escrever alguns testes para fazer benchmarks de tempos de resposta para API (sem necessidade de tempos extremamente precisos).
kashiraja