javascript - 为什么重新分配函数指针会减慢函数调用

标签 javascript performance pointers benchmarking

我一直在使用函数指针p 来调用不同的函数。我的问题是,如果我在已经为它分配了一个函数后将它指向另一个函数,调用 p 的性能会急剧下降。如果我一遍又一遍地在 undefined 和同一个函数之间切换 p 性能很好,当我只将它指向一个函数时性能很好,但是在函数之间切换会降低性能.

下面是我用来测试这个场景的代码,这里是 fiddle .我以递归方式循环 500 次,并在每个循环中调用 p 1,000,000 次。 p 可以是 undefined 或指向 func1func2

function func1() {} // two identical empty functions
function func2() {} // different in name only

var p = func1; // default to func1

var count  = 0; // current loop
var elapse = 0; // elapsed time for 1,000,000 calls on each loop
var start  = 0; // start time for 1,000,000 calls on each loop
var total  = 0; // total elapsed time for all loops

function loop() {

  start = performance.now(); // get start time

  for (let i = 0; i < 1000000; i ++) if (p !== undefined) p(); // do 1,000,000 calls or early out 1,000,000 times if undefined

    elapse = performance.now() - start;

  total += elapse; // used for getting average

  count ++;

  console.log(p + "\nelapsed " + elapse + "\naverage " + total / count);

  // Switch between the lines below to see the performance difference.
  p = (p === func1) ? p = undefined : p = func1; // best performance
  //p = (p === func1) ? p = func1 : p = func1; // good performance
  //p = (p === func1) ? p = func2 : p = func1; // bad performance

  // pattern: func1 -> undefined -> func2 -> undefined -> repeat
  /*if (p === undefined) p = (count % 4 === 0) ? p = func1 : p = func2;
  else p = undefined;*/ // also bad performance

  if (count < 500) loop(); // start the next loop

}

console.clear();

loop(); // start the loop

为什么调用 p 的性能在分配给不同的函数时会显着下降?另外,为什么在将 p 设置为 undefined 时,将 p 设置为 undefined 并返回原始函数不会改变性能然后到不同的功能呢?

最佳答案

您正在阻止引擎创建优化的热路径,因为它不能依赖函数指针的值。

请参阅本文中标题为“JavaScript 引擎中的解释器/编译器管道”的部分:https://mathiasbynens.be/notes/shapes-ics

图片显示了 TurboFan 基于执行分析数据优化字节码,以及其后的文字说明:

To make it run faster, the bytecode can be sent to the optimizing compiler along with profiling data. The optimizing compiler makes certain assumptions based on the profiling data it has, and then produces highly-optimized machine code.

If at some point one of the assumptions turns out to be incorrect, the optimizing compiler deoptimizes and goes back to the interpreter.

当您重新分配函数指针时,您会将冲突的分析数据从解释器发送到编译器。当您分配未定义时不会发生这种情况,因为在这种情况下不会执行该代码路径:if (p !== undefined) p();

关于javascript - 为什么重新分配函数指针会减慢函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56381296/

相关文章:

javascript - 阻止 &lt;input&gt; 元素在 iPhone 上滚动屏幕?

javascript - 需要优化的解决方案,并且不使用 jquery 函数

android - 查询大表并在代码中执行逻辑或执行大量查询.. 哪个更有效?

c++ - head->next 不为空

c - 结构定义中的结构指针

带有字符串和索引的 JavaScript 类型强制

javascript - 如何模仿 GChat 的可滚动区域?

swift - 如何让 swift 在合理的时间内编译出基础数学

c++ - 如何将指向数组的指针初始化为成员变量

javascript - 更新日期或添加日期后日期选择器图标消失