优化/function运行时,v8状态码会发生什么变化?
我看到了一个关于v8优化的问题,这让我在v8优化中玩了一下。 我也看到蓝鸟发布有关v8 优化杀手 。
根据v8回购,优化状态代码是2:1,2,4,8等乘法(请参阅OptimizationStatus枚举)
但是,下面的代码给了我奇怪的状态代码,如17和65,只在这些特定的情况下(见最后几行代码)。 任何想法为什么发生这种情况?
function adder(a, b) { return new Function('a', 'b', 'return b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b')(a, b); } function addereval(a, b) { return eval('b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b'); } function printStatus(fn) { var status = %GetOptimizationStatus(fn) switch (status) { case 1: console.log(fn.name, "function is optimized"); break; case 2: console.log(fn.name, "function is not optimized"); break; case 3: console.log(fn.name, "function is always optimized"); break; case 4: console.log(fn.name, "function is never optimized"); break; case 6: console.log(fn.name, "function is maybe deoptimized"); break; case 7: console.log(fn.name,"Function is optimized by TurboFan"); break; default: console.log(fn.name, "Unknown optimization status: ", status); break; } } printStatus(adder); printStatus(addereval); for(let i = 0; i < 263; i++) { adder(1, 2); } console.log('\n', '==== adder after invocation - result is on node v8.2.1 17 or 65 on node v8.7.0 ==='); printStatus(adder); addereval(1, 2); console.log('\n', '==== addereval after invocation - result is 65 ==='); printStatus(addereval);
运行以下代码:
node --trace_deopt --allow-natives-syntax FILENAME.js
如果你觉得它更舒适,你可以使用我的要点
status
是一个按位标志值,代码应该看起来更像这样:
var status = GetOptimizationStatus(fn); if ((status & (1 << 0)) { console.log(fn.name, "kIsFunction"); } if ((status & (1 << 1)) { console.log(fn.name, "kNeverOptimize"); } // etc .. can be 'true' for several different combinations; // most notably, many different status will also include 'kIsFunction'
考虑17〜或〜16 16 + 1
1〜或〜 (1 << 4) | (1 << 0)
的“状态码” (1 << 4) | (1 << 0)
〜表示〜“kIsFunction” 和 “kIsOptimized”。
查看位arrays的一般操作 – 以及为什么在代码中显示的条件使用&
。
%GetOptimizationStatus
已更新为返回一组按位标志,而不是一个单一的值,文章Optimization Killers已过时。 可用的状态信息也稍有改变。
要访问新值,您需要获取返回值的二进制表示forms。 现在,例如,如果返回65
,则二进制表示如下:
65₁₀ = 000001000001₂
每个二进制数字作为一个布尔值,其含义如下:
0 0 0 0 0 1 0 0 0 0 0 1 ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ │ │ │ │ │ │ └─╸ is function │ │ │ │ │ │ │ │ │ │ └───╸ is never optimized │ │ │ │ │ │ │ │ │ └─────╸ is always optimized │ │ │ │ │ │ │ │ └───────╸ is maybe deoptimized │ │ │ │ │ │ │ └─────────╸ is optimized │ │ │ │ │ │ └───────────╸ is optimized by TurboFan │ │ │ │ │ └─────────────╸ is interpreted │ │ │ │ └───────────────╸ is marked for optimization │ │ │ └─────────────────╸ is marked for concurrent optimization │ │ └───────────────────╸ is optimizing concurrently │ └─────────────────────╸ is executing └───────────────────────╸ topmost frame is turbo fanned
因此, 65
表示该函数是一个函数并被解释(这意味着在查询其状态时,它不是最优化的)。
要在JavaScript中访问这些值,只需使用按位AND运算符并查看该值是否为非零值:
var status = %GetOptimizationStatus(fn); if (status & 1) console.log("function is function"); if (status & 2) console.log("function is never optimized"); if (status & 4) console.log("function is always optimized"); if (status & 8) console.log("function is maybe deoptimized"); if (status & 16) console.log("function is optimized"); if (status & 32) console.log("function is optimized by TurboFan"); if (status & 64) console.log("function is interpreted"); ...
等等。 这里的关键是不止一个条件可以评估为真。