benchmark.js的示例应用程序将其性能测试定义为字符串而不是JavaScript函数:
https://github.com/bestiejs/benchmark.js/blob/master/example/jsperf/index.html#L250
以这种方式定义性能测试是否有优势?为什么它不仅仅是一个功能?
答案 0 :(得分:1)
据我所知,通过一系列的调用,函数代码最终出现在名为getSource的函数in benchmark.js中,无论如何都会将其转换为字符串:
/**
* Gets the source code of a function.
*
* @private
* @param {Function} fn The function.
* @param {String} altSource A string used when a function's source code is unretrievable.
* @returns {String} The function's source code.
*/
function getSource(fn, altSource) {
var result = altSource;
if (isStringable(fn)) {
result = String(fn);
} else if (support.decompilation) {
// escape the `{` for Firefox 1
result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
}
// trim string
result = (result || '').replace(/^\s+|\s+$/g, '');
// detect strings containing only the "use strict" directive
return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
? ''
: result;
}
这是在函数“clock”中完成的,它提供了另一种解释,说明每次调用时钟时用字符串制作基准函数的动机:
// Compile in setup/teardown functions and the test loop.
// Create a new compiled test, instead of using the cached `bench.compiled`,
// to avoid potential engine optimizations enabled over the life of the test.
我不是benchmark.js的专家,但我对它的解读是,库故意想从原始代码启动基准测试,迫使编译器/解释器运行以前从未见过的代码。这对我来说很有意义,因为假设浏览器在加载时冻结五秒以优化代码可能会有惊人的性能,但忽略它在基准测试中编译的五秒钟是不公平的。此外,它对原始代码进行了相当多的修改,以便控制范围和异常处理;基准测试只需要将代码作为字符串来正确操作它。
在这个视图中,将函数作为字符串传递并不是特别重要,但是没有理由不这样做 - 它最终会以字符串形式结束。
答案 1 :(得分:0)
在这种情况下,将函数添加为字符串或引用对测试性能没有影响。
请看下面的benchmark.js#L336和示例。文档说这取决于你。
您可能需要查看clock
函数:benchmark.js#L2452。您将看到,如果函数作为引用传递,它将转换为字符串。更重要的是整个测试是作为一个字符串创建的。
我不知道为什么它是一个更好的解决方案的所有优点,但我想到了这些:
我想要注意的是,我指出的所有优点都与运行代码的技术方面无关。如果是字符串,则必须对其进行解释并执行定义的次数。然后检查已经过了多少时间,这是基准测试的结果(基本上)。整个概念是一样的:
var counter = N,
after,
before = performance.now;
while(counter--) {
myFun();
}
after = performance.now;
console.log(after - before);