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

时间:2021-07-21 16:10:15

Is there a package that helps me benchmark JavaScript code? I'm not referring to Firebug and such tools.

是否有帮助我对JavaScript代码进行基准测试的软件包?我不是指Firebug和这样的工具。

I need to compare 2 different JavaScript functions that I have implemented. I'm very familiar with Perl's Benchmark (Benchmark.pm) module and I'm looking for something similar in JavaScript.

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

Has the emphasis on benchmarking JavaScript code gone overboard? Can I get away with timing just one run of the functions?

重点是JavaScript代码的基准测试是否过分?我可以通过一次运行来计算时间吗?

8 个解决方案

#1


23  

Just time several iterations of each function. One iteration probably won't be enough, but (depending on how complex your functions are) somewhere closer to 100 or even 1,000 iterations should do the job.

只需对每个函数进行多次迭代。一次迭代可能是不够的,但是(取决于你的功能有多复杂),接近100或甚至1000次迭代的地方应该可以胜任。

Firebug also has a profiler if you want to see which parts of your function are slowing it down.

如果你想看看你的功能的哪些部分正在减慢它,Firebug也有一个分析器。

Edit: To future readers, the below answer recommending JSPerf should be the correct answer. I would delete mine, but I can't because it has been selected by the OP. There is much more to benchmarking than just running many iterations, and JSPerf takes care of that for you.

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

#2


95  

jsperf.com is the go-to site for testing JS performance. Start there. If you need a framework for running your own tests from the command line or scripts use Benchmark.js, the library upon which jsperf.com is built.

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

Note: Anyone testing Javascript code should educate themselves on the pitfalls of "microbenchmarks" (small tests that target a specific feature or operation, rather than more complex tests based on real-world code patterns). Such tests can be useful but are prone to inaccuracy due to how modern JS runtimes operate. Vyacheslav Egorov's presentation on performance and benchmarking is worth watching to get a feel for the nature of the problem(s).

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

Edit: Removed references to my JSLitmus work as it's just no longer relevant or useful.

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

#3


53  

Just adding a quick timer to the mix, which someone may find useful:

只需添加一个快速计时器,有人可能会觉得有用:

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

Ideally it would be placed in a class, and not used as a global like I did for example purposes above. Using it would be pretty simple:

理想情况下,它将被放置在一个类中,并不像上面的示例目的那样用作全局。使用它会非常简单:

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

#4


19  

I have been using this simple implementation of @musicfreaks answer. There are no features, but it is really easy to use. This bench(function(){return 1/2;}, 10000, [], this) will calculate 1/2 10,000 times.

我一直在使用@musicfreaks答案的这个简单实现。没有功能,但它真的很容易使用。这个工作台(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;  
};

#5


10  

Just simple way.

只是简单的方法。

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

#6


7  

It’s really hard to write decent cross-browser benchmarks. Simply timing a pre-defined number of iterations of your code is not bulletproof at all.

编写像样的跨浏览器基准测试真的很难。简单地对代码的预定义迭代次数进行计时根本不是防弹的。

As @broofa already suggested, check out jsPerf. It uses Benchmark.js behind the scenes.

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

#7


2  

if writing a custom benchmark script be sure to note that some browsers apply dom manipulations only after function in which they are defined is ended. More details here http://www.quirksmode.org/blog/archives/2009/08/when_to_read_ou.html

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

#8


1  

If you need something simple you can do like this:

如果你需要一些简单的东西,你可以这样做:

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

Here is an example of the code

这是代码的一个例子

#1


23  

Just time several iterations of each function. One iteration probably won't be enough, but (depending on how complex your functions are) somewhere closer to 100 or even 1,000 iterations should do the job.

只需对每个函数进行多次迭代。一次迭代可能是不够的,但是(取决于你的功能有多复杂),接近100或甚至1000次迭代的地方应该可以胜任。

Firebug also has a profiler if you want to see which parts of your function are slowing it down.

如果你想看看你的功能的哪些部分正在减慢它,Firebug也有一个分析器。

Edit: To future readers, the below answer recommending JSPerf should be the correct answer. I would delete mine, but I can't because it has been selected by the OP. There is much more to benchmarking than just running many iterations, and JSPerf takes care of that for you.

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

#2


95  

jsperf.com is the go-to site for testing JS performance. Start there. If you need a framework for running your own tests from the command line or scripts use Benchmark.js, the library upon which jsperf.com is built.

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

Note: Anyone testing Javascript code should educate themselves on the pitfalls of "microbenchmarks" (small tests that target a specific feature or operation, rather than more complex tests based on real-world code patterns). Such tests can be useful but are prone to inaccuracy due to how modern JS runtimes operate. Vyacheslav Egorov's presentation on performance and benchmarking is worth watching to get a feel for the nature of the problem(s).

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

Edit: Removed references to my JSLitmus work as it's just no longer relevant or useful.

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

#3


53  

Just adding a quick timer to the mix, which someone may find useful:

只需添加一个快速计时器,有人可能会觉得有用:

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

Ideally it would be placed in a class, and not used as a global like I did for example purposes above. Using it would be pretty simple:

理想情况下,它将被放置在一个类中,并不像上面的示例目的那样用作全局。使用它会非常简单:

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

#4


19  

I have been using this simple implementation of @musicfreaks answer. There are no features, but it is really easy to use. This bench(function(){return 1/2;}, 10000, [], this) will calculate 1/2 10,000 times.

我一直在使用@musicfreaks答案的这个简单实现。没有功能,但它真的很容易使用。这个工作台(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;  
};

#5


10  

Just simple way.

只是简单的方法。

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

#6


7  

It’s really hard to write decent cross-browser benchmarks. Simply timing a pre-defined number of iterations of your code is not bulletproof at all.

编写像样的跨浏览器基准测试真的很难。简单地对代码的预定义迭代次数进行计时根本不是防弹的。

As @broofa already suggested, check out jsPerf. It uses Benchmark.js behind the scenes.

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

#7


2  

if writing a custom benchmark script be sure to note that some browsers apply dom manipulations only after function in which they are defined is ended. More details here http://www.quirksmode.org/blog/archives/2009/08/when_to_read_ou.html

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

#8


1  

If you need something simple you can do like this:

如果你需要一些简单的东西,你可以这样做:

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

Here is an example of the code

这是代码的一个例子