gpt4 book ai didi

javascript - 函数范围内与函数外声明函数的性能

转载 作者:行者123 更新时间:2023-12-01 16:26:24 24 4
gpt4 key购买 nike

我在思考是否在函数作用域内和在作用域外声明函数的性能影响。

为此,我使用 jsperf 创建了一个测试,结果对我来说很有趣,我希望有人能解释这里发生的事情。

测试:https://jsperf.com/saarman-fn-scope/1

谷歌浏览器结果:
chrome results

Microsoft Edge 结果:
edge results

Firefox 结果:
enter image description here

最佳答案

V8 开发人员在这里。简而言之:您已成为微基准测试陷阱的受害者。实际上,“测试 1”的效率稍高一些,但取决于您的整体程序,差异可能太小了。

“测试 1”更有效的原因是它创建的闭包更少。把它想象成:

let mathAdd = new Function(...);
for (let i = 0; i < 1000; i++) {
mathAdd();
}

对比
for (let i = 0; i < 1000; i++) {
let mathAdd = new Function(...);
mathAdd();
}

就像您正在调用 new Object()new MyFunkyConstructor() 一样,在循环外只执行一次会更有效,而不是在每次迭代时执行。

“测试 1”似乎较慢的原因是测试设置的人工产物。在这种情况下,jsperf.com 将您的代码包装成函数的具体方式恰好在这种情况下击败了 V8 的内联机制 [1]。所以在“测试 1”中, run 是内联的,但 mathAdd 不是,因此执行了实际调用,并进行了实际添加。另一方面,在“测试 2”中, runmathAdd 都被内联,编译器随后发现结果未被使用,并消除了所有死代码,因此您正在对空循环进行基准测试:它不创建任何函数,不调用任何函数,也不执行任何加法(除了 i++ )。

随意检查生成的汇编代码以自己查看:-)
事实上,如果您想创建更多的微基准测试,您应该习惯于检查汇编代码,以确保基准测试测量您认为它正在测量的内容。

[1] 我不知道为什么;如果我不得不猜测:可能有特殊处理来检测这样一个事实,即虽然每次测试用例运行时 run 都是一个新的闭包,但它下面的代码总是相同的,但看起来这种特殊情况只适用于本地函数调用的范围,而不是像 runmathAdd 调用那样从上下文链加载。如果猜测是正确的,您可以将其称为错误(Firefox 显然没有);另一方面,如果唯一的影响是微基准测试中的死代码消除不再起作用,那么这当然不是一个需要解决的重要问题。

关于javascript - 函数范围内与函数外声明函数的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60357206/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com