JavaScript 函数何时在 V8 环境中优化?

When is a JavaScript function optimized in a V8 environment?

我正在尝试了解以下 TypeScript 函数在从 JavaScript 到某些 V8 环境中的机器代码的过程中是否以及在哪一点以及在多大程度上进行了优化例如:

function foo(): number {
  const a = 1;
  const b = a;
  const c = b + 1;
  return c;
}

该函数使用不带参数的常量进行运算,因此它始终等同于以下函数:

function foo(): number {
  return 1 + 1;
}

最终在任何字节码或机器代码中,只需将数字 2 分配给某个寄存器,而无需中间分配值或从一个寄存器到另一个寄存器的指针。

假设优化这种简单的逻辑是微不足道的,我可以想象可能发生的几个潜在步骤:

  1. 将 TypeScript 编译为 JavaScript
  2. 从JavaScript
  3. 生成抽象语法树
  4. 从 AST 生成字节码
  5. 从字节码生成机器码
  6. 根据即时编译重复步骤 4

这种优化是否发生,或者从性能的角度来看,将表达式分配给常量以提高可读性是否是一种不好的做法?

(此处为 V8 开发人员。)

Does this optimization happen

是的,当函数运行得足够热以进行优化时,它就会发生。优化后的代码确实只会将 2 写入 return 寄存器。

解析器、解释器和基线编译器通常不应用任何优化。原因是识别优化机会往往比简单地执行一些操作要花费更多的时间,所以只有当函数被大量执行时,做这项工作才会有回报。

此外,如果您要在该函数中间设置一个断点并在调试器中检查局部状态,您会希望看到所有三个局部变量以及它们是如何逐步分配的,所以引擎也必须考虑到这种可能性。

is it a bad practice from the performance point of view to assign expressions to constants for better readability?

不,这样做完全没问题。即使它确实花费了您一两条机器指令,拥有可读代码通常更为重要。

当可读性更强的实现让您意识到可以简化整个算法时,尤其如此。 CPU 每秒可以执行数十亿条指令,因此节省少量指令不会有太大变化;但是,如果您有机会将线性扫描替换为恒定时间查找,则可以节省足够的计算工作(一旦您的数据变得足够大),从而产生巨大的不同。