You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中函数后续调用执行速度为何远快于首次调用?

p1: 0.921ms

p1: 0.522ms

p1a: 1.128ms

p1a: 0.485ms

p1a: 0.508ms

如果调换函数的调用顺序,会得到如下输出:

p1a: 3.511ms

p1a: 1.102ms

p1a: 0.468ms

p1: 1.046ms

p1: 0.567ms

p1: 0.542ms

核心问题分为两部分:
1. 为什么完全相同的函数连续运行3次时,后续每次调用的执行速度都会逐次变快?
2. 为什么`p1`在首个调用时运行耗时为3.52ms,但在`p1a`之后调用时仅耗时1.046ms?反过来`p1a`先调用、`p1`后调用时也存在同样的现象,原因是什么?

---
## 解答
### 问题1解答
该现象由JavaScript引擎(常见为Node.js/Chrome使用的V8引擎)的即时编译(JIT)和运行时优化机制直接导致:
- 第一次调用函数时,引擎以解释模式执行字节码,同时收集函数参数、内部变量的类型信息,无任何编译优化,叠加初始化开销所以耗时最长。
- 第二次调用时,函数被识别为热点代码,引擎将其编译为基线机器码,跳过解释步骤直接执行,同时内联缓存(IC)完成预热,`forEach`回调、字符串拆分、数组索引访问等操作的类型判断可以直接命中缓存,不需要动态查询,速度大幅提升。
- 第三次调用时,引擎基于前两次收集的稳定类型信息做激进优化编译,包括小函数内联、冗余类型检查消除、循环优化等,同时输入数据已经常驻CPU高速缓存,内存访问延迟进一步降低,速度达到稳定峰值。

### 问题2解答
两个函数首次调用的耗时差异,来源于先执行的函数已经完成了大量公共运行时预热工作:
- 两个函数核心逻辑高度相似,都用到了字符串拆分数组遍历、数组`forEach`迭代、二进制字符串转数字`parseInt`、`console`输出等通用操作,先执行的函数已经完成了这些通用API的内联缓存初始化、字节码编译,后执行的函数可以直接复用这些优化结果,不需要重复支付冷启动开销。
- 输入的`input`数组在首次访问时会触发操作系统的页缺失(Page Fault),加载完成后会留在物理内存和CPU缓存中,后续不管哪个函数访问这个数组,内存访问速度都会远高于第一次冷加载。
- 两个函数用到的数组、字符串对象的隐藏类(Shape)已经被先执行的函数稳定下来,后续属性访问不需要动态计算偏移量,进一步降低了首次调用的开销。

---
内容的提问来源于stack exchange,提问作者dsf190
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:54:03