2017-07-02 117 views
1

我想了解在更好的細節的最大堆棧幀/大小。洞察V8最大堆棧幀/尺寸

function computeMaxCallStackFrames() { 
    try { 
     // 
     // <Variable part here> 
     // 
     return 1 + computeMaxCallStackFrames(); 
    } catch (e) { 
     // Call stack overflow 
     return 1; 
    } 
} 
computeMaxCallStackFrames() // 5447 on Chrome 58.0.3029.110, Mac 10.11 

更改// <Variable part here>到:

測試用例1:

var a = 1; 
// computeMaxCallStackFrames() => 5220 

測試用例2:

var a = 1; 
var b = 2;  
// computeMaxCallStackFrames() => 5011 

測試用例3:

var a = 1; 
var b = {};  
// computeMaxCallStackFrames() => 5011 (no change from `var b = 2;`) 

測試案例4:

var a = 1; 
var b = {c: 3};  
// computeMaxCallStackFrames() => 5010 

我的問題是,爲什麼在所有Test case 4變化,以及爲什麼它由1個少棧幀變化。

**編輯**任何相關的鏈接到V8的來源將是夢幻般的。即使只顯示堆棧大小內存限制的設置也是很好的介紹。在Andreas Rossberg和jmrk分別留下他們的偉大回答和評論時,不要問這個問題。

回答

2

有可能影響在V8和其它JS引擎的個人堆棧幀的大小很多很多的因素:例如,參數的數目,變量的數量,這些變量的續航時間,如何將這些變量使用,無論它們是否在內部閉包中捕獲,是否存在try-handlers,函數中發生了哪些其他操作(可能需要內部臨時變量),甚至是之前傳遞給函數的實際參數的類型。而且,這一切都取決於運行時概要分析和函數的優化級別(以及可能調用的其他函數),這些級別可能會隨時間而改變,甚至取決於編譯/優化/去優化的時間,這可能有些不確定。

這是所有說 - 一如既往 - 微基準測試不會給有用的信息,在最壞的情況是大爲誤導。你真的需要衡量你關心的具體程序。

+0

明白了,希望有人可能會說了這一切;)也希望有人可能會跟進鏈接到V8源代碼表示在檢測空未突變對象的某些評論或測試用例並提出引用一些現有的空對象當新的非空對象被放到堆中,然後相同的,未改變的,未被訪問的對象只是引用...大問我知道。 – AJP

+1

+1對此答案。要添加一個小數據點:如果使用'--print-bytecode',您可以看到該函數的幀大小在情況2,3,4中是相同的(我在最近的版本中看到了「48」;使用了不同的版本的值可能不同)。因此,它不是'computeMaxCallStackFrames'本身,而是當對象文字非空時,系統中某處使用了更多堆棧空間。 – jmrk

+1

@ AJP的評論:如果你想問另一個問題,請提出另一個問題。簡短的回答是,對象文字處理比您的建議複雜得多。並且沒有對象的「重複數據刪除」(空/未修改或其他),因爲標識是可觀察的:'var a = {}; var b = {}; a === b/* - > false * /' – jmrk