122

是否有一个包可以帮助我对 JavaScript 代码进行基准测试?我不是指 Firebug 和此类工具。

我需要比较我已经实现的 2 个不同的 JavaScript 函数。我对 Perl 的 Benchmark ( Benchmark.pm ) 模块非常熟悉,我正在寻找 JavaScript 中类似的东西。

对 JavaScript 代码进行基准测试的强调是否过火了?我可以只计时一次功能吗?

4

8 回答 8

122

jsperf.com是测试 JS 性能的首选站点。从那里开始。如果您需要一个框架来从命令行或脚本运行您自己的测试,请使用Benchmark.js,这是构建 jsperf.com 的库。

注意:任何测试 Javascript 代码的人都应该了解“微基准”的陷阱(针对特定功能或操作的小型测试,而不是基于真实世界代码模式的更复杂的测试)。此类测试可能很有用,但由于现代 JS 运行时的运行方式,容易出现不准确的情况。 Vyacheslav Egorov 关于性能和基准测试的演示值得一看,以了解问题的本质。

编辑:删除了对我的 JSLitmus 工作的引用,因为它不再相关或有用。

于 2010-11-29T16:06:55.283 回答
93

只是简单的方法。

console.time('test');
console.timeEnd('test');
于 2017-10-09T15:16:36.307 回答
80

只需在组合中添加一个快速计时器,有人可能会觉得这很有用:

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
于 2014-09-16T20:45:47.947 回答
38

只需对每个函数进行几次迭代。一次迭代可能还不够,但是(取决于您的函数的复杂程度)接近 100 甚至 1,000 次迭代应该可以完成这项工作。

如果您想查看函数的哪些部分使其变慢,Firebug 也有一个分析器。

编辑:对于未来的读者,下面推荐 JSPerf 的答案应该是正确的答案。我会删除我的,但我不能,因为它已被 OP 选中。基准测试不仅仅是运行多次迭代,而 JSPerf 会为您处理这些。

于 2009-06-16T20:50:53.177 回答
20

我一直在使用@musicfreaks 答案的这个简单实现。没有任何功能,但它真的很容易使用。这bench(function(){return 1/2;}, 10000, [], this)将计算 1/2 10,000 次。

/**
 * 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;  
};
于 2011-01-10T06:51:43.223 回答
9

编写体面的跨浏览器基准测试真的很难。简单地计时代码的预定义迭代次数根本不是万无一失的

正如@broofa 已经建议的那样,请查看jsPerf。它在幕后使用Benchmark.js 。

于 2011-02-16T11:25:35.853 回答
2

如果编写自定义基准脚本,请务必注意某些浏览器仅在定义它们的函数结束后才应用 dom 操作。更多细节在这里 http://www.quirksmode.org/blog/archives/2009/08/when_to_read_ou.html

于 2011-09-14T19:07:03.663 回答
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)

这是代码示例

于 2016-08-04T00:57:46.770 回答