Mar*_*ico 6 javascript performance v8 function
我正在考虑是否在函数作用域内和作用域外声明函数对性能的影响。
为此,我使用 jsperf 创建了一个测试,结果对我来说很有趣,我希望有人可以解释这里发生了什么。
测试: https: //jsperf.com/saarman-fn-scope/1
jmr*_*mrk 10
V8 开发者在这里。简而言之:您已经成为微基准测试陷阱的受害者。实际上,“测试 1”的效率稍高一些,但根据您的整体程序,差异可能太小而无关紧要。
\n\n“测试 1”更高效的原因是它创建的闭包更少。将其视为:
\n\nlet mathAdd = new Function(...);\nfor (let i = 0; i < 1000; i++) {\n mathAdd();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n与
\n\nfor (let i = 0; i < 1000; i++) {\n let mathAdd = new Function(...);\n mathAdd();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n就像您调用new Object()or一样new MyFunkyConstructor(),仅在循环外执行一次而不是每次迭代都更有效。
“测试 1”看起来较慢的原因是测试设置的产物。在这种情况下,jsperf.com 将代码包装到函数中的具体方式恰好击败了 V8 的内联机制 [1]。因此,在“测试 1”中,run是内联的,但mathAdd不是,因此执行了实际的调用,并进行了实际的加法。另一方面,在“测试 2”中, 和 都run被mathAdd内联,编译器随后发现结果未被使用,并消除了所有死代码,以便您对空循环进行基准测试:它不创建任何函数,不调用任何函数函数,并且不执行加法(除了i++)。
请随意检查生成的汇编代码以亲自查看:-)\n事实上,如果您想创建进一步的微基准测试,您应该习惯于检查汇编代码,以确保基准测试测量您的想法\的测量。
\n\n[1] I\'m not sure why; if I had to guess: there\'s probably special handling to detect the fact that while run is a new closure every time the test case runs, it\'s always the same code underneath, but it looks like that special-casing only applies to functions in the local scope of the call, not to loads from the context chain as in the run\xe2\x86\x92mathAdd call. If that guess is correct, you could call it a bug (which Firefox apparently doesn\'t have); on the other hand, if the only impact is that dead-code elimination in microbenchmarks doesn\'t work any more, then it\'s certainly not an important issue to fix.