JIT与GC优化

最后更新于:2022-04-01 04:51:49

## `JIT`与`GC`优化 > * `untyped`(无类型)。 > > > * `JAVASCRIPT`是个无类型的语言,这导致了如`x=y+z`这种表达式可以有很多含义。 > > > * `y`,`z`是数字,则`+`表示加法。 > * `y`,`z`是字符串,则`+`表示字符串连接。 > > 而JS引擎内部则使用“`细粒度`”的类型,比如: > > > * 32-bit* integer。 > * 64-bit* floating-point。 > > 这就要求js类型-js引擎类型,需要做“boxed/unboxed(装箱/解箱)”,在处理一次`x=y+z`这种计算,需要经过的步骤如下。 > > > 1. 从内存,读取`x=y+z`的操作符。 > 2. 从内存,读取`y`,`z`。 > 3. 检查y,z类型,确定操作的行为。 > 4. `unbox y,z`。 > 5. 执行操作符的行为。 > 6. `box x`。 > 7. 把`x`写入内存。 > > 只有第`5`步骤是真正有效的操作,其他步骤都是为第`5`步骤做准备/收尾,`JAVASCRIPT`的`untyped`特性很好用,但也为此付出了很大的性能代价。 > > > * `JIT`。 > > > * 先看看`JIT`对`untyped`的优化,在`JIT`下,执行`x=y+z`流程。 > > > 1. 从内存,读取`x=y+z`的操作符。 > 2. 从内存,读取 `y`,`z`。 > 3. 检查`y`,`z`类型,确定操作的行为。 > 4. `unbox y,z`。 > 5. 执行 操作符 的行为。 > 6. `box x`。 > 7. 把`x`写入内存。 > > 其中`1`,`2`步骤由`CPU`负责,`7`步骤`JIT`把结果保存在寄存器里。但可惜不是所有情况都能使用JIT,当`number+number`,`string+string` 等等可以使用`JIT`,但特殊情况,如:`number+undefined`就不行了,只能走旧解析器。 > > > * 新引擎还对“对象属性”访问做了优化,解决方案叫`inline caching`,简称:`IC`。简单的说,就是做`cache`。但如果当`list`很大时,这种方案反而影响效率。 > * `Type-specializing JIT` > > > > > `Type-specializing JIT`引擎用来处理`typed`类型(声明类型)变量,但`JAVASCRIPT`都是`untype`类型的。 > > > * `Type-specializing JIT`的解决方案是: > * 先通过扫描,监测类型。 > * 通过编译优化(优化对象不仅仅只是“类型”,还包括对JS代码的优化,但核心是类型优化),生成类型变量。 > * 再做后续计算。 > * `Type-specializing JIT`的执行`x=y+z`流程: > > > * 从内存,读取`x=y+z`的操作符。 > * 从内存,读取`y`,`z`。 > * 检查`y`,`z`类型,确定操作的行为。 > * `unbox y,z`。 > * 执行操作符的行为。 > * `box x`。 > * 把`x`写入内存。 > > 代价是: > > > * 前置的扫描类型 > * 编译优化。 > > 所以·Type-specializing JIT·的应用是有选择性,选择使用这个引擎的场景包括: > > > * 热点代码。 > * 通过启发式算法估算出来的有价值的代码。 > > 另外,有2点也需要注意: > > > * 当变量类型 发生变化时,引擎有2种处理方式: > * 少量变更,重编译,再执行。 > * 大量变更,交给JIT执行。 > * `数组`,`object properties`, 闭包变量 不在优化范畴之列。
';