涡轮增压: JIT 编译优化

一图流

语言范式的根本矛盾和调和

编译型语言

  • 预先编译成机器相关的机器码(执行效率高)
  • 强类型支持静态内存布局(执行&内存效率高)
  • 函数调用采用固定偏移量寻址
  • 执行效率比解释器高 10 - 100 倍

解释型语言

  • 灵活
  • 访问属性需要哈希查找
  • eval 等特性导致无法预知的上下文污染
  • 闭包链管理开销

JIT 哲学

运行时类型特化

runtime Specialization

哲学本质:将动态类型转换为静态类型信息,在保证语言灵活性的前提下创造确定性的优化空间

隐藏类系统(Hidden Class)

  • 相同构造方式的对象共享隐藏类
csharp 复制代码
 // 构造器顺序决定隐藏类结构
function A() { this.x = 1; this.y = 2 }  // 隐藏类C1
function B() { this.y = 2; this.x = 1 }  // 隐藏类C2(与C1不同) 
  • 属性访问转换为固定偏移量查找
ini 复制代码
; 机器码示例(x64)
mov rax, [obj + 0x18]  ; 直接内存偏移访问

内联缓存(Inline Cache)

  • 记录最近10次调用点的类型信息
  • 生成特化的机器码片段
javascript 复制代码
function add(x, y) {
  return x + y; // 根据x,y类型生成特化代码
}
  • 单态调用(单一类型)速度接近C++
  • 多态调用(2-4种类型)性能下降50%
  • 超多态(5+类型)退化为哈希查找

投机优化

speculative Optimization

哲学本质:基于概率统计的预测执行,用空间换时间换取大概率性能提升

类型预测(Type Prediction)

ini 复制代码
 // 热代码段的类型假设
for (let i = 0; i < 1e6; i++) {
  sum += arr[i]; // 假设arr元素始终是SMALL_INTEGER
}
  • 生成带类型检查的机器码
ini 复制代码
cmp qword [rax], 0x1a3  ; 检查隐藏类
jne deoptimization      ; 跳转到去优化例程

分支预测(Branch Prediction)

  • 记录循环条件的历史走向
  • 预编译最可能的执行路径

典型案例:

sql 复制代码
 // 引擎会优先优化true分支
if (condition) { /* 执行概率90% */ } 
else { /* 10%概率 */ }

渐进式编译

tiered Compilcation

哲学本质:在编译开销与执行效率之间动态平衡,实现冷热代码区别对待

从解释到提前编译的升级过程(基于函数/循环的迭代次数判断是否编译)

  1. 解释执行,生成紧凑字节码(收集反馈信息)
  2. 基线编译器(baseLine)生成简单优化的机器码(编译耗时1ms内)
  3. 优化编译器(Trubofan) ,激进的进行优化(编译耗时 10 - 100ms)

去优化陷阱

deoptimization Bailout

哲学本质:承认预测可能失败,建立安全回退机制保障正确性

对于

  1. 属性类型突变
  2. 函数多态

会承认优化无效,抛弃优化代码。重建解释器

去优化 > 3 次则永久禁用优化

最佳实践

了解JS引擎的优化思路,以避免写出反优化的代码

经过高效优化的JS在浏览器中能够达到C++的70%以上

  1. 避免元素类型震荡

js 对于同种类型的数组会采用不同的内存格式策略

ini 复制代码
const arr = [1,2,3];         // PACKED_SMI_ELEMENTS
arr.push(4.5);               // → PACKED_DOUBLE_ELEMENTS
arr[2] = {};                 // → PACKED_ELEMENTS
  1. 避免动态属性破坏隐藏类
ini 复制代码
// 反模式代码
function createObj() {
  const obj = {};
  for (let i = 0; i < 10; i++) {
    obj[`prop${i}`] = i; // 每次迭代改变隐藏类
  }
  return obj;
}
  1. 使用类型稳定的数组和结构稳定的对象

笔者才疏学浅,各位读者多多担待,不吝赐教。

相关推荐
kidding7239 分钟前
微信小程序怎么分包步骤(包括怎么主包跳转到分包)
前端·微信小程序·前端开发·分包·wx.navigateto·subpackages
微学AI24 分钟前
详细介绍:MCP(大模型上下文协议)的架构与组件,以及MCP的开发实践
前端·人工智能·深度学习·架构·llm·mcp
liangshanbo12151 小时前
CSS 包含块
前端·css
Mitchell_C1 小时前
语义化 HTML (Semantic HTML)
前端·html
倒霉男孩1 小时前
CSS文本属性
前端·css
shoa_top1 小时前
JavaScript 数组方法总结
javascript
晚风3081 小时前
前端
前端
JiangJiang1 小时前
🚀 Vue 人如何玩转 React 自定义 Hook?从 Mixins 到 Hook 的华丽转身
前端·react.js·面试
鱼樱前端1 小时前
让人头痛的原型和原型链知识
前端·javascript
用户19727304821961 小时前
传说中的开发增效神器-Trae,让我在开发智能旅拍小程序节省40%时间
前端