如何对 JavaScript 代码进行基准测试?

IT技术 javascript benchmarking
2021-02-19 23:00:19

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

我需要比较我实现的 2 个不同的 JavaScript 函数。我非常熟悉 Perl 的 Benchmark ( Benchmark.pm ) module,我正在寻找类似的 JavaScript 内容。

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

6个回答

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

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

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

我想使用 jsperf,但它似乎在计算在一段时间内可以运行代码的次数,而不是为 N 循环的实际调用计时。我希望他们有一个选择。
2021-04-16 23:00:19
更新:只需使用 jsperf.com - 它变得更好了,并且非常适合这种事情。jslitmus 仍然有效,但已经有一段时间没有积极开发了。
2021-04-30 23:00:19
@Jeach - jsperf 给出“操作数/秒”。只需将该值乘以您的代码将运行的时间(以秒为单位)。
2021-05-03 23:00:19
这是上乘的答案。+1
2021-05-06 23:00:19
更新:jsperf 不再在线,何时恢复在线也没有任何消息。有关更多信息,请参阅此 github 线程
2021-05-10 23:00:19

只是简单的方法。

console.time('test');
console.timeEnd('test');
您可能还想在测试套件中运行您的基准测试,这需要访问计时器值。
2021-04-20 23:00:19
这应该是公认的答案。使用第三方服务有时并不方便,仅使用简单的内置功能就很好。
2021-05-08 23:00:19
@brainbag - 问题是关于基准测试,它涉及的不仅仅是对一段代码运行多长时间进行计时。此外,控制台计时器仅在有问题的代码花费超过 1 毫秒(其分辨率的限制)时才有用。
2021-05-09 23:00:19

只需在混合中添加一个快速计时器,有人可能会发现它很有用:

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
为了获得更准确的结果,人们可能希望使用developer.mozilla.org/en-US/docs/Web/API/Performance/nowperformance.now()而不是Date()
2021-04-16 23:00:19
typescript版本:pastebin.com/gCs9CB5F
2021-04-27 23:00:19
对于 node.js,您可以使用process.hrtime()获得纳秒分辨率。
2021-04-27 23:00:19
正是我需要的 - timeIt()
2021-05-04 23:00:19
在这里很好地使用了闭包。
2021-05-15 23:00:19

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

Firebug 也有一个分析器,如果你想查看你的函数的哪些部分会减慢它的速度。

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

当然,没有冒犯的伙伴。我只是想我会评论以供将来参考,因为已经对这个主题进行了更多的研究。
2021-04-15 23:00:19
简单地对代码的预定义迭代次数进行计时根本不是万无一失的此外,打开 Firebug 会禁用 Firefox 的即时 (JIT) 编译器,这意味着测试将在解释器中运行,即比其他情况下慢得多。使用 Firebug 的分析器不会给您预期的结果。
2021-05-03 23:00:19
@Mathias:好吧,公平地说,这个答案真的很旧。
2021-05-10 23:00:19
或者使用jsben.ch因为 jsperf 已关闭
2021-05-15 23:00:19

我一直在使用@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;  
};