【问题标题】:if some function is not optimized does it mean that all functions where it is declared are not optimized either?如果某些函数未优化,是否意味着声明它的所有函数也未优化?
【发布时间】:2015-03-22 17:52:06
【问题描述】:

最近看到了optimization killers这篇关于V8引擎对JavaScript程序优化的文章。但是这篇文章对我来说并不完全清楚,所以我想问几个关于这个东西的问题。

文章称:

优化编译器编译的代码可以很容易地比通用编译器生成的代码快 100 倍... 请务必注意,导致优化 bailouts 的模式会影响整个包含函数。

这是否意味着,例如,如果某个大型代码,比如说一个 JavaScript 库,它是一种 IIFE(立即调用函数表达式)形式,其中包含一个 try {} catch(e) {} 语句被另一个函数声明包裹,那么整个库没有优化?

好像是这样,因为我尝试运行这个命令$ node --trace_opt --trace_deopt --allow-natives-syntax try_catch.js,而try_catch.js在下面:

//Function that contains the pattern to be inspected (using with statement)
function optimizeWhack() {
    foo();
    function foo() {
        try {} catch(e) {}
    }
    return 12
}

function printStatus(fn) {
    switch(%GetOptimizationStatus(fn)) {
        case 1: console.log("Function is optimized"); break;
        case 2: console.log("Function is not optimized"); break;
        case 3: console.log("Function is always optimized"); break;
        case 4: console.log("Function is never optimized"); break;
        case 6: console.log("Function is maybe deoptimized"); break;
    }
}

//Fill type-info
optimizeWhack();

%OptimizeFunctionOnNextCall(optimizeWhack);
//The next call
optimizeWhack();

//Check
printStatus(optimizeWhack);

我得到的回复是这个,function is not optimized

$ node --trace_opt --trace_deopt --allow-natives-syntax try_catch.js 
[deoptimize context: ea2f6f14679]
[optimizing: optimizeWhack / ea2f6fc9c29 - took 0.033, 0.064, 0.000 ms]
**** DEOPT: optimizeWhack at bailout #1, address 0x0, frame size 8
[deoptimizing: begin 0xea2f6fc9c29 optimizeWhack @1]
  translating optimizeWhack => node=3, height=8
    0x7fff113fa238: [top + 40] <- 0xd7de9006c91 ; [sp + 40] 0xd7de9006c91 <JS Global Object>
    0x7fff113fa230: [top + 32] <- 0x1bca01a663fc ; caller's pc
    0x7fff113fa228: [top + 24] <- 0x7fff113fa268 ; caller's fp
    0x7fff113fa220: [top + 16] <- 0xea2f6f14679; context
    0x7fff113fa218: [top + 8] <- 0xea2f6fc9c29; function
    0x7fff113fa210: [top + 0] <- 0xea2f6fca051 ; rbx 0xea2f6fca051 <JS Function foo>
[deoptimizing: end 0xea2f6fc9c29 optimizeWhack => node=3, pc=0x1bca01a665ff, state=NO_REGISTERS, alignment=no padding, took 0.074 ms]
[removing optimized code for: optimizeWhack]
Function is not optimized

一个更普遍的问题是向我指出一些关于所有这些优化内容的文献、资料等(如果有的话)。

提前谢谢你。

【问题讨论】:

  • “一个更普遍的问题是向我指出一些关于所有这些优化内容的文献、资料等,如果它们存在的话。” 题外话。
  • “提前谢谢你。”这里是多余的!
  • 你基本上没有在问题本身中回答这个问题吗?大声笑
  • @LightnessRacesinOrbit 不,我不回答。因为我的脚本的输出状态为Function is not optimized,我不能确定这是真的(脚本可能有一些错误的逻辑,而且现在最常推荐的方法是模块模式,对于许多任务,提示我认为这些陈述有问题,例如,AngularJS 几乎不可能运行完全未优化等),这就是为什么我要向更有经验的人寻求建议。

标签: javascript optimization v8


【解决方案1】:

V8 的优化编译器是基于函数的,因此如果它无法优化某些不影响任何其他函数的函数 - 包括那些包含此不可优化函数声明的函数。

优化编译器不支持的几乎所有语句也仅具有局部效果 - 它们禁用包含它们的特定函数的优化,但不影响包含该函数的函数。但是有一个例外:直接eval 会影响所有封闭函数。

function foo() {
  function bar() {
    function baz() {
      eval(str);
    }
  }
}

在上面的示例中,foobarbaz 均无法通过 V8 的曲轴进行优化。

现在以您的示例为例:从日志中您可以看到 optimizeWhack 在您要求优化后确实得到了优化

[optimizing: optimizeWhack / ea2f6fc9c29 - took 0.033, 0.064, 0.000 ms]

但是当执行进入优化函数时,它会去优化

*** DEOPT: optimizeWhack at bailout #1, address 0x0, frame size 8
[deoptimizing: begin 0xea2f6fc9c29 optimizeWhack @1]

deopt 的原因如下:因为您执行了optimizeWhack 一次调用IC 在foo() 进入单态状态并且V8 对特定函数值的调用进行了特殊调用。但是,下次您调用 optimizeWack 时,会创建一个 new foo,它不再匹配上一次调用中预期的 foo 值。这会导致 deopt。

如果您在请求优化之前重写示例以调用 optimizeWhack 两次,那么您将看到 optimizeWhack 保持优化:

optimizeWhack();
optimizeWhack();

%OptimizeFunctionOnNextCall(optimizeWhack);
optimizeWhack();

printStatus(optimizeWhack);

// $ d8 --allow-natives-syntax test.js
// Function is optimized

【讨论】:

  • 谢谢,但我看不懂第一句话。我是否应该将其解读为 V8 的优化编译器是基于函数的,因此它能够优化任何不影响任何其他函数的函数——包括那些包含此不可优化函数声明的函数。
  • @user907860 让我改述一下。 V8 的优化编译器逐个函数编译您的代码。如果它不能编译一个函数(例如调用foo)——那只适用于那个函数和那个函数。如果 foo 实际上包含在函数 bar 中 - bar 仍然可以使用优化编译器进行编译,除非它本身包含错误的构造。
猜你喜欢
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2015-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
相关资源
最近更新 更多