2017-10-14 83 views
5

我看到一個關於v8 Optimization的問題,這導致我在v8優化中玩了一下。 我也見過bluebird post about v8 Optimization killers優化/函數運行時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 

您可以使用my gist,如果你發現它更舒適

+2

它們是位域,由多個標誌組成。你所描述的「狀態代碼」是訪問返回值中個別標誌的掩碼。 – Bergi

+2

另外,請注意,「優化殺手」文件已過時,因爲它談到了已經退役的「曲軸」編譯器。從Chrome M59/Node.js 8.3開始,V8使用「Turbofan」,它可以優化一切。(有些構造總是比其他構造慢,但是Turbofan的設計永遠不會因爲任何原因拒絕優化整個函數。) – jmrk

回答

3

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' 

考慮「狀態碼」1716 + 1或〜(1 << 4) | (1 << 0),這意味着「kIsFunction」「kIsOptimized」。

查看bit arrays的一般操作 - 以及爲什麼在代碼中顯示的條件使用&

4

%GetOptimizationStatus已更新爲返回一組按位標誌而不是單個值,並且文章Optimization Killers已過期。可用的狀態信息也略有變化。

要訪問新值,需要獲取返回值的二進制表示形式。現在,例如,如果返回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"); 
... 

等。這裏的關鍵是不止一個條件可以評估爲真。

+0

您知道GetOptimizationStatus的返回值何時更新? – liuyanghejerry

+1

@liuyanghejerry - 我不確定,但肯定會返回一組按位標誌(在這個答案中提到)在58和更高版本。 –

相關問題