最近我遇到了关于V8引擎优化JavaScript程序的文章optimization killers。但这篇文章对我来说并不完全清楚,所以我想问一下这个问题。
文章指出:
优化编译器编译的代码可以轻松地比通用编译器生成的代码快100倍... 值得注意的是,导致优化纾困的模式会影响整个包含函数。
这是否意味着,例如,如果有一大段代码,假设一个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
一个更普遍的问题是指向一些文献,来源等。关于所有这些优化的东西,如果那些存在的话。
提前谢谢。
答案 0 :(得分:5)
V8的优化编译器是基于函数的,因此如果它无法优化某些不影响任何其他函数的函数 - 包括那些包含此不可优化函数声明的函数。
几乎所有优化编译器都不支持的语句也只有本地效果 - 它们禁用包含它们的特定函数的优化,但不影响包含该函数的函数。但是有一个例外:直接eval
会对所有封闭函数产生影响。
function foo() {
function bar() {
function baz() {
eval(str);
}
}
}
在上面的例子中,foo
,bar
,baz
都不能被V8的Crankshaft优化。
现在举例来说:从日志中可以看出,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
时,会创建一个新 foo
,该 foo
不再匹配上次调用的预期optimizeWhack
值。这导致deopt。
如果您在请求优化之前重写示例以致电optimizeWhack
两次,那么您会看到optimizeWhack();
optimizeWhack();
%OptimizeFunctionOnNextCall(optimizeWhack);
optimizeWhack();
printStatus(optimizeWhack);
// $ d8 --allow-natives-syntax test.js
// Function is optimized
保持优化:
{{1}}