Jak mogę porównać kod JavaScript? [Zamknięte]


106

Czy istnieje pakiet, który pomaga mi testować kod JavaScript? Nie mam na myśli Firebuga i takich narzędzi.

Muszę porównać 2 różne funkcje JavaScript, które wdrożyłem. Bardzo dobrze znam moduł Perl's Benchmark ( Benchmark.pm ) i szukam czegoś podobnego w JavaScript.

Czy nacisk na benchmarking kodu JavaScript przesadził? Czy mogę uciec z synchronizacją tylko jednego uruchomienia funkcji?


Wydaje się być
dupkiem


Wiem, że to nie jest kuloodporne iw ogóle, ale i tak powiązane: czasami po prostu chcesz wiedzieć, jak mierzyć czas potrzebny do wykonania funkcji .
Skippy le Grand Gourou

1
I dobre narzędzie do testów porównawczych JavaScript, które można znaleźć tutaj: jsben.ch
EscapeNetscape

Odpowiedzi:


36

Po prostu wykonaj kilka iteracji każdej funkcji. Jedna iteracja prawdopodobnie nie wystarczy, ale (w zależności od tego, jak złożone są twoje funkcje) gdzieś bliżej 100 lub nawet 1000 iteracji powinno załatwić sprawę.

Firebug ma również profiler, jeśli chcesz zobaczyć, które części funkcji spowalniają ją.

Edycja: dla przyszłych czytelników poniższa odpowiedź zalecająca JSPerf powinna być poprawną odpowiedzią. Usunąłbym mój, ale nie mogę, ponieważ został wybrany przez OP. Benchmarking to znacznie więcej niż tylko wykonywanie wielu iteracji, a JSPerf zajmie się tym za Ciebie.


12
Samo mierzenie wstępnie zdefiniowanej liczby iteracji kodu nie jest w ogóle niezawodne . Otwarcie Firebuga wyłącza również kompilator JIT (Just-In-Time) Firefoksa, co oznacza, że ​​testy będą wykonywane w interpreterze, tj. Znacznie wolniej niż w innym przypadku. Korzystanie z profilera Firebuga nie przyniesie oczekiwanych wyników.
Mathias Bynens,

1
@Mathias: Cóż, żeby być uczciwym, ta odpowiedź jest naprawdę stara.
Sasha Chedygov

2
Jasne, bez obrazy kolego. Pomyślałem, że skomentuję to w przyszłości, teraz, gdy przeprowadzono więcej badań na ten temat.
Mathias Bynens,

4
Lub użyj jsben.ch, ponieważ jsperf nie działa
EscapeNetscape

118

jsperf.com to strona docelowa do testowania wydajności JS. Zacznij tam. Jeśli potrzebujesz frameworka do wykonywania własnych testów z wiersza poleceń lub skryptów, użyj Benchmark.js , biblioteki, na której zbudowana jest witryna jsperf.com.

Uwaga: każdy, kto testuje kod JavaScript, powinien zapoznać się z pułapkami związanymi z „mikropunktami” (małe testy ukierunkowane na określoną funkcję lub operację, a nie bardziej złożone testy oparte na wzorcach kodu w świecie rzeczywistym). Takie testy mogą być przydatne, ale są podatne na niedokładność ze względu na sposób działania nowoczesnych środowisk wykonawczych JS. Warto obejrzeć prezentację Wiaczesława Jegorowa na temat wydajności i testów porównawczych, aby poczuć naturę problemu (ów).

Edycja: Usunięto odniesienia do mojej pracy JSLitmus, ponieważ nie jest już ona odpowiednia ani przydatna.


3
Aktualizacja: po prostu użyj jsperf.com - jest dużo lepszy i działa naprawdę dobrze w tego typu sytuacjach. jslitmus nadal działa, ale nie był aktywnie rozwijany od dłuższego czasu.
broofa

To jest najlepsza odpowiedź. +1
Justin Force

1
Chciałem użyć jsperf, ale wydaje się, że liczy on, ile razy może uruchomić kod w danym okresie, zamiast mierzyć czas rzeczywistego wywołania pętli N. Szkoda, że ​​nie mieli możliwości wyboru.
Jeach

1
@Jeach - jsperf podaje "operacje / sekundę". Po prostu pomnóż tę wartość przez czas (w sekundach), przez który kod będzie działał.
broofa

4
Aktualizacja: jsperf nie jest już online i nie wiadomo, kiedy będzie ponownie online. Zobacz wątek na githubie, aby uzyskać więcej informacji.
James Gould

74

Dodanie do miksu szybkiego timera, który może się przydać:

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

Idealnie byłoby, gdyby został umieszczony w klasie i nie używany jako globalny, tak jak zrobiłem to na przykład w celach powyżej. Używanie tego byłoby całkiem proste:

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

6
Dobre użycie zamknięć tutaj.
Dandy

12
Aby uzyskać dokładniejszy wynik, można użyć performance.now()zamiast Date() developer.mozilla.org/en-US/docs/Web/API/Performance/now
thormeier

Właśnie tego potrzebowałem - a timeIt ()
Gishu,


1
W przypadku node.js możesz użyć process.hrtime (), aby uzyskać rozdzielczość nanosekundową.
Xeoncross,

57

Po prostu prosty sposób.

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

3
To powinna być akceptowana odpowiedź. Korzystanie z usługi innej firmy czasami nie jest wygodne, a samo użycie prostej wbudowanej funkcji jest doskonałe.
torebka mózgowa

1
@brainbag - pytanie dotyczyło testów porównawczych, które obejmują coś więcej niż tylko określenie czasu działania fragmentu kodu. Ponadto liczniki czasu konsoli są przydatne tylko wtedy, gdy dany kod zajmuje więcej niż 1 milisekundę (limit ich rozdzielczości).
broofa

Możesz również chcieć uruchomić test porównawczy w zestawie testów, który wymaga dostępu do wartości licznika czasu.
JamesDev

20

Korzystałem z tej prostej implementacji odpowiedzi @musicfreaks. Nie ma żadnych funkcji, ale jest naprawdę łatwy w użyciu. To bench(function(){return 1/2;}, 10000, [], this)obliczy 1/2 10000 razy.

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



1

Jeśli potrzebujesz czegoś prostego, możesz to zrobić:

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

Oto przykład kodu


Prosty był zdecydowanie najlepszą opcją w moim przypadku ... napisanie kilku testów porównujących czasy odpowiedzi dla API (nie ma potrzeby bardzo dokładnych czasów).
kashiraja
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.