Chrome DevTools性能分析中,循环调用空函数时run函数Self Time占比过高的原因探究
解答:为什么空函数场景下调用者的Self Time远高于叶子函数?
这是个非常贴近引擎底层细节的好问题,核心原因要结合Chrome DevTools的性能统计规则和V8引擎的优化逻辑来拆解:
首先得明确Chrome DevTools里Self Time的核心定义:
Self Time 指的是函数自身执行代码的耗时,完全不包含它调用其他子函数的时间。反之,子函数的执行耗时会被计入调用者的总耗时(Total Time),但不会计入调用者的Self Time。
你的问题可以拆解为两个关键原因:
1. 函数调用的开销被计入了调用者的Self Time
当run调用func时,JavaScript引擎(V8)需要执行一系列前置/后置操作:
- 创建新的调用栈帧
- 保存当前执行上下文(比如
run里的i变量状态) - 跳转到
func的执行入口 - 执行完
func后销毁栈帧、恢复run的上下文 - 继续执行
run的循环逻辑
这些操作不属于func内部的代码执行,而是run发起调用的动作开销,所以会被直接计入run的Self Time。你这里调用了10万次func,累积的调用开销非常可观。
2. V8引擎的死代码消除优化让func几乎没有实际执行耗时
你写的func内部循环是完全无意义的:
for(let i = 0; i < 1000; i++) { i *= 10 i /= 10 }
这段代码不会产生任何可观察的副作用(既不修改外部变量,也不返回值),V8的优化编译器(TurboFan)会在编译阶段直接把这段循环完全删除(死代码消除,Dead Code Elimination)。最终func实际执行的代码几乎为0,自然不会占用多少Self Time。
验证结论的小实验
如果你想确认这个逻辑,可以做两个小修改:
- 在
func里加入有副作用的代码,比如window.test = i或者console.log(i),这样V8就无法消除循环,func的Self Time会立刻飙升 - 减少
run里的调用次数(比如改成1000次),你会发现run的Self Time也会大幅下降,因为调用开销减少了
内容的提问来源于stack exchange,提问作者EnderShadow8
相关产品推荐
相关产品推荐

