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`, 闭包变量 不在优化范畴之列。