Як можна порівняти код JavaScript? [зачинено]


104

Чи є пакет, який допомагає мені орієнтувати код JavaScript? Я не маю на увазі Firebug та подібні інструменти.

Мені потрібно порівняти дві різні функції JavaScript, які я реалізував. Я дуже знайомий з модулем Benchmark ( Benchmark.pm ) Perl і шукаю щось схоже в JavaScript.

Чи зробив акцент на тестуванні коду JavaScript за борт? Чи можу я відійти від часу лише запустити функції?




Я знаю, що це не пуленепробивально і все, але все одно пов'язане: іноді просто хочеться знати, як виміряти час, який займає функція для виконання .
Skippy le Grand Gourou

1
Я хороший інструмент орієнтиру JavaScript, який ви можете знайти тут: jsben.ch
EscapeNetscape

Відповіді:


36

Тільки раз декілька ітерацій кожної функції. Однієї ітерації, ймовірно, буде недостатньо, але (залежно від того, наскільки складні ваші функції) десь ближче до 100 або навіть 1000 ітерацій, це повинно зробити цю роботу.

У Firebug також є профілер, якщо ви хочете побачити, які частини вашої функції сповільнюють його.

Редагувати: Для майбутніх читачів правильною відповіддю має бути відповідь, що рекомендує JSPerf. Я б видалив шахту, але не можу, тому що вона була обрана ОП. Для порівняльного тестування є набагато більше, ніж просто виконання багатьох ітерацій, і JSPerf опікується цим для вас.


12
Просто встановлення часу заздалегідь визначеної кількості ітерацій вашого коду зовсім не вільне . Крім того, відкриття Firebug вимикає компілятор Firefox Just-In-Time (JIT), а це означає, що тести працюватимуть в інтерпретаторі, тобто набагато повільніше, ніж це було б інакше. Використання профіля Firebug не дасть вам очікуваних результатів.
Mathias Bynens

1
@Mathias: Ну, якщо чесно, ця відповідь справді стара.
Саша Чедигов

2
Звичайно, товариш не ображається. Я просто думав, що буду коментувати для подальшого ознайомлення тепер, коли було проведено більше досліджень з цього питання.
Mathias Bynens

4
Або скористайтеся jsben.ch, оскільки jsperf не працює
EscapeNetscape

118

jsperf.com - це найважливіший сайт для тестування продуктивності JS. Почніть з цього. Якщо вам потрібна основа для запуску власних тестів з командного рядка або скриптів, використовуйте Benchmark.js , бібліотеку, на якій побудовано jsperf.com.

Примітка. Кожен, хто тестує код Javascript, повинен навчатись про підводні камені "мікробензикових позначок" (невеликі тести, орієнтовані на певну особливість чи операцію, а не на більш складні тести, засновані на моделях реального коду). Такі тести можуть бути корисними, але схильні до неточності через те, як працюють сучасні умови виконання JS. Презентацію В'ячеслава Єгорова про ефективність та бенчмаркінг варто переглянути, щоб зрозуміти характер проблеми.

Редагувати: Видалені посилання на мою роботу JSLitmus, оскільки вона більше не є актуальною чи корисною.


3
Оновлення: просто використовуйте jsperf.com - це набагато краще, і він працює дуже добре для подібних речей. jslitmus все ще працює, але вже активно не розробляється протягом тривалого часу.
брофа

Це найкраща відповідь. +1
Джастін Форс

1
Я хотів використовувати jsperf, але, здається, підраховує, скільки разів він може запустити код за певний проміжок часу, а не призначати фактичний виклик для N циклів. Я б хотів, щоб у них був вибір на вибір.
Jeach

1
@Jeach - jsperf дає "операції / секунди". Просто помножте це значення на час (у секундах), для якого буде виконуватися код.
брофа

4
Оновлення: jsperf більше не в Інтернеті, і немає слова, коли він повернеться в Інтернет. Дивіться цю тему github для отримання додаткової інформації.
Джеймс Гулд

73

Просто додайте в суміш швидкий таймер, який може бути корисним:

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

В ідеалі він був би розміщений у класі, а не використовувався як глобальний, як я це робив, наприклад, для вищезгаданих цілей. Використовувати його було б досить просто:

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

6
Тут добре використовувати закриття.
Денді

12
Для більш точного результату, можливо, ви хочете використовувати performance.now()замість Date() developer.mozilla.org/en-US/docs/Web/API/Performance/now
thormeier

Якраз те, що мені було потрібно - timeIt ()
Gishu


1
Для node.js ви можете використовувати process.hrtime () для отримання наносекундної роздільної здатності.
Xeoncross

56

Просто простий спосіб.

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

3
Це має бути прийнятою відповіддю. Користуватися стороннім сервісом іноді не зручно, і просто використання простої вбудованої функції є відмінним.
мішечок

1
@brainbag - Питання стосувалося бенчмаркінгу, який передбачає більше, ніж просто встановлення часу, як триває трохи коду. Також консольні таймери корисні лише в тому випадку, якщо відповідний код займає більше 1 мілісекунди (межа їх роздільної здатності).
брофа

Ви також можете запустити орієнтир у тестовому наборі, для якого потрібно мати доступ до значення таймера.
JamesDev

20

Я використовував цю просту реалізацію відповіді @musicfreaks. Немає функцій, але це справді просто у використанні. Це bench(function(){return 1/2;}, 10000, [], this)обчислить 1/2 10000 разів.

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

9

Написати гідні крос-браузерні орієнтири дуже важко. Просто встановлення часу заздалегідь визначеної кількості ітерацій вашого коду зовсім не вільне .

Як @broofa вже запропонував, перевірте jsPerf . Він використовує Benchmark.js поза кадром.



1

Якщо вам потрібно щось просте, ви можете зробити так:

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

Ось приклад коду


Простий, безумовно, був найкращим варіантом у моєму випадку ... написання деяких тестів для орієнтування часу відповіді для API (не потрібно вкрай точні часи).
kashiraja
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.