2017-07-02 116 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