Как я могу протестировать код JavaScript? [закрыто]

106

Есть ли пакет, который помогает мне тестировать код JavaScript? Я не имею в виду Firebug и подобные инструменты.

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

Неужели упор на тестирование кода JavaScript переборщил? Могу ли я обойтись без тайминга всего лишь одного запуска функций?

Ионный морж
источник
Кажется,
дубликат
Возможный дубликат Как вы проверяете производительность кода JavaScript?
Джон Слегерс
Я знаю, что это не пуленепробиваемое и все такое, но все равно связано: иногда вы просто хотите знать, как измерить время, затрачиваемое функцией на выполнение .
Скиппи ле Гран Гуру,
1
Хороший инструмент для тестирования JavaScript можно найти здесь: jsben.ch
EscapeNetscape,

Ответы:

36

Просто рассчитайте несколько итераций каждой функции. Одной итерации, вероятно, будет недостаточно, но (в зависимости от сложности ваших функций) где-то около 100 или даже 1000 итераций должны выполнить свою работу.

Firebug также имеет профилировщик, если вы хотите увидеть, какие части вашей функции замедляют ее.

Изменить: для будущих читателей приведенный ниже ответ, рекомендующий JSPerf, должен быть правильным ответом. Я бы удалил свой, но не могу, потому что он был выбран OP. Бенчмаркинг - это гораздо больше, чем просто выполнение множества итераций, и JSPerf позаботится об этом за вас.

Саша Чедыгов
источник
12
Простое определение времени заранее определенного количества итераций вашего кода вовсе не является пуленепробиваемым . Кроме того, открытие Firebug отключает компилятор Firefox Just-In-Time (JIT), что означает, что тесты будут выполняться в интерпретаторе, то есть намного медленнее, чем в противном случае. Использование профилировщика Firebug не даст ожидаемых результатов.
Матиас Байненс
1
@Mathias: Ну, честно говоря, этот ответ действительно старый.
Саша Чедыгов
2
Конечно, без обид, дружище. Я просто подумал, что прокомментирую для справки в будущем, когда по этому поводу было проведено больше исследований.
Матиас Байненс,
4
Или используйте jsben.ch, поскольку jsperf не работает
EscapeNetscape
118

jsperf.com - это сайт для тестирования производительности JS. Начни там. Если вам нужен фреймворк для запуска ваших собственных тестов из командной строки или сценариев, используйте Benchmark.js , библиотеку, на которой построен jsperf.com.

Примечание. Любой, кто тестирует код Javascript, должен изучить подводные камни «микробенчмарков» (небольших тестов, нацеленных на конкретную функцию или операцию, а не более сложных тестов, основанных на реальных шаблонах кода). Такие тесты могут быть полезны, но они подвержены неточностям из-за того, как работают современные среды выполнения JS. Стоит посмотреть презентацию Вячеслава Егорова о производительности и тестировании , чтобы понять суть проблемы (-ов).

Изменить: удалены ссылки на мою работу JSLitmus, поскольку она больше не актуальна и не полезна.

брофа
источник
3
Обновление: просто используйте jsperf.com - он стал намного лучше и отлично работает для подобных вещей. jslitmus по-прежнему работает, но уже довольно давно активно не развивается.
broofa
Это превосходный ответ. +1
Джастин Форс
1
Я хотел использовать jsperf, но, похоже, он подсчитывает, сколько раз он может запускать код в течение определенного периода времени, а не рассчитывает фактический вызов N циклов. Я бы хотел, чтобы у них была возможность выбора.
Jeach
1
@Jeach - jsperf дает «операций в секунду». Просто умножьте это значение на время (в секундах), в течение которого будет выполняться код.
broofa
4
Обновление: jsperf больше не в сети, и нет ни слова, когда он вернется в сеть. См. Эту ветку github для получения дополнительной информации.
Джеймс Гулд,
74

Просто добавьте в микс быстрый таймер, который может кому-то пригодиться:

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
Версия TypeScript: pastebin.com/gCs9CB5F
Александр Тейлор,
1
Для node.js вы можете использовать process.hrtime () для получения наносекундного разрешения.
Xeoncross
57

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

console.time('test');
console.timeEnd('test');
stadnik0ff
источник
3
Это должен быть принятый ответ. Иногда использование сторонних сервисов неудобно, и просто использовать простую встроенную функцию отлично.
brainbag
1
@brainbag - вопрос касался бенчмаркинга, который включает в себя нечто большее, чем просто определение времени выполнения части кода. Кроме того, консольные таймеры полезны только в том случае, если рассматриваемый код занимает более 1 миллисекунды (предел их разрешения).
broofa
Вы также можете запустить свой тест в наборе тестов, для которого требуется доступ к значению таймера.
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;  
};
fncomp
источник
9

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

Как уже предлагал @broofa, попробуйте jsPerf . Он негласно использует Benchmark.js .

Матиас Байненс
источник
2

при написании собственного тестового сценария обязательно обратите внимание, что некоторые браузеры применяют dom-манипуляции только после завершения функции, в которой они определены. Подробнее здесь http://www.quirksmode.org/blog/archives/2009/08/when_to_read_ou.html

Лукинс
источник
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