深入了解 v8 最大堆栈帧/大小

Insight into v8 max stack frames / size

我想更详细地了解最大堆栈帧/大小。

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 已经分别留下了很好的答案和评论时没有提出这个问题。

有很多很多因素会影响 V8 和其他 JS 引擎中单个堆栈帧的大小:例如,参数的数量、变量的数量、这些变量的生命周期、这些变量如何是否被使用,它们是否在内部闭包中被捕获,是否有 try-handlers,函数中发生了哪些其他操作(可能在内部需要临时变量),甚至传递给函数的实际参数的类型前。此外,这完全取决于运行时分析和函数(以及它可能调用的其他函数)的优化级别,这可能会随着时间而改变,甚至取决于它是 compiled/optimised/deoptimised 的时间,这在某种程度上可能是不确定的。

这就是说——一如既往——微基准不会提供有用的信息,最坏的情况是会产生严重的误导。您确实需要衡量您关心的具体程序。