加载中...

JIT与GC优化


  • untyped(无类型)。

    • JAVASCRIPT是个无类型的语言,这导致了如x=y+z这种表达式可以有很多含义。

      • yz是数字,则+表示加法。
      • yz是字符串,则+表示字符串连接。

      而JS引擎内部则使用“细粒度”的类型,比如:

      • 32-bit* integer。
      • 64-bit* floating-point。

      这就要求js类型-js引擎类型,需要做“boxed/unboxed(装箱/解箱)”,在处理一次x=y+z这种计算,需要经过的步骤如下。

      1. 从内存,读取x=y+z的操作符。
      2. 从内存,读取yz
      3. 检查y,z类型,确定操作的行为。
      4. unbox y,z
      5. 执行操作符的行为。
      6. box x
      7. x写入内存。

      只有第5步骤是真正有效的操作,其他步骤都是为第5步骤做准备/收尾,JAVASCRIPTuntyped特性很好用,但也为此付出了很大的性能代价。

  • JIT

    • 先看看JITuntyped的优化,在JIT下,执行x=y+z流程。

      1. 从内存,读取x=y+z的操作符。
      2. 从内存,读取 yz
      3. 检查yz类型,确定操作的行为。
      4. unbox y,z
      5. 执行 操作符 的行为。
      6. box x
      7. x写入内存。

      其中12步骤由CPU负责,7步骤JIT把结果保存在寄存器里。但可惜不是所有情况都能使用JIT,当number+numberstring+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的操作符。
      • 从内存,读取yz
      • 检查yz类型,确定操作的行为。
      • unbox y,z
      • 执行操作符的行为。
      • box x
      • x写入内存。

      代价是:

      • 前置的扫描类型
      • 编译优化。

      所以·Type-specializing JIT·的应用是有选择性,选择使用这个引擎的场景包括:

      • 热点代码。
      • 通过启发式算法估算出来的有价值的代码。

      另外,有2点也需要注意:

      • 当变量类型 发生变化时,引擎有2种处理方式:
        • 少量变更,重编译,再执行。
        • 大量变更,交给JIT执行。
      • 数组object properties, 闭包变量 不在优化范畴之列。

还没有评论.