首页 > 其他分享 >乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 超前预编译AOT和即时编译JIT

乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 超前预编译AOT和即时编译JIT

时间:2022-08-26 20:22:51浏览次数:99  
标签:字节 编译器 代码 跨平台 编译 JIT Net 执行

什么是即时编译JIT

在计算机领域,即时编译(Just In Time, JIT)(也是动态编译或运行时编译)是一种执行计算机代码的方式,它涉及在程序执行期间(运行时)而不是在执行之前进行编译。这可能包括源代码翻译,但更常见的是字节码翻译成机器码,然后直接执行。实现JIT编译器的系统通常会持续分析正在执行的代码,并确定代码的哪些部分从编译或重新编译中获得的速度会超过编译该代码的开销。

image

JIT编译是两种传统的机器码翻译方法的结合,即时间先期编译(AOT)和解释,并结合了两者的一些优点和缺点。粗略地说,JIT编译结合了编译代码的速度和解释的灵活性,以及解释器的开销和编译和连接(不仅仅是解释)的额外开销。JIT编译是动态编译的一种形式,并允许自适应优化,如动态重新编译和针对微架构的速度提升。解释和JIT编译特别适用于动态编程语言,因为运行时系统可以处理迟来的数据类型并执行安全保证。

设计原理

在字节码编译的系统中,源代码被翻译成一种被称为字节码的中间表示。字节码不是任何特定计算机的机器代码,并且可以在计算机架构之间移植。然后,字节码可以被虚拟机解释,或在虚拟机上运行。JIT编译器以许多部分(或全部,很少)读取字节码,并将其动态编译为机器代码,以便程序可以更快地运行。这可以在每个文件、每个函数甚至任何任意的代码片段上进行;代码可以在即将执行时被编译(因此被称为 "即时"),然后缓存并在以后重新使用而不需要重新编译

相比之下,传统的解释型虚拟机将简单地解释字节码,通常性能低得多。有些解释器甚至可以解释源代码,而不需要先编译成字节码,其性能甚至更差。静态编译的代码或本地代码在部署之前就已经被编译了。动态编译环境是指在执行过程中可以使用编译器。使用JIT技术的一个共同目标是达到或超过静态编译的性能,同时保持字节码解释的优势。在部署之前,解析原始源代码和执行基本优化的大部分"繁重工作"通常在编译时处理:从字节码到机器码的编译比从源代码编译快得多。部署的字节码是可移植的,与本地代码不同。由于运行时对编译有控制权,就像解释的字节码一样,它可以在安全的沙盒中运行。从字节码到机器码的编译器更容易编写,因为可移植的字节码编译器已经完成了很多工作。

JIT代码通常提供比解释器好得多的性能。此外,在某些情况下,它可以提供比静态编译更好的性能,因为许多优化只有在运行时才是可行的

  • 编译可以根据目标CPU和应用程序运行的操作系统模型进行优化。例如,JIT在检测到CPU支持SSE2矢量CPU指令时可以选择这些指令。为了用静态编译器获得这种水平的优化特性,必须为每个目标平台/架构编译一个二进制文件,或者在一个二进制文件中包括代码的部分的多个版本。

  • 该系统能够收集关于程序在其所处环境中实际运行情况的统计数据,它可以重新安排和重新编译以获得最佳性能。然而,一些静态编译器也可以把配置文件信息作为输入。

  • 系统可以进行全局代码优化(如库函数的内联),而不会失去动态链接的优势,也不会出现静态编译器和链接器固有的开销。具体来说,在做全局内联替换时,静态编译过程可能需要运行时检查,并确保如果对象的实际类覆盖了内联方法,就会发生虚拟调用,而且在循环中可能需要处理数组访问的边界条件检查。在许多情况下,通过即时编译,这种处理可以从循环中移出,通常可以大大增加速度

  • 尽管静态编译的垃圾回收语言也可以做到这一点,但字节码系统可以更容易地重新安排已执行的代码,以便更好地利用缓存

由于JIT必须在运行时渲染和执行本地二进制映像,真正的机器码JIT必须有允许在运行时执行数据的平台,因此在基于哈佛架构的机器上使用这种JIT是不可能的;对于某些操作系统和虚拟机也是如此。然而,一种特殊类型的"JIT"有可能不针对物理机的CPU架构,而是针对优化的虚拟机字节码,其中对原始机器代码的限制占了上风,特别是当该字节码的虚拟机最终利用JIT来处理本地代码时。

性能表现

由于加载和编译字节码所需的时间,JIT在应用程序的初始执行中会造成轻微到明显的延迟。有时这种延迟被称为"启动时间延迟"或"预热时间"。一般来说,JIT执行的优化越多,它生成的代码就越好,但初始延迟也会增加。因此,JIT编译器必须在编译时间和它希望生成的代码的质量之间做出权衡。启动时间除了JIT编译之外,还可能包括增加的IO绑定操作:例如,Java虚拟机(JVM)的rt.jar类数据文件是40MB,JVM必须在这个上下文巨大的文件中寻找大量的数据。

Sun公司的HotSpot Java虚拟机所使用的一种可能的优化是把解释和JIT编译结合起来。应用程序代码最初是被解释的,但JVM监控哪些字节码序列经常被执行,并将它们翻译成机器代码,以便在硬件上直接执行。对于只执行几次的字节码,这可以节省编译时间并减少初始延迟;对于经常执行的字节码,JIT编译被用来在缓慢解释的初始阶段后高速运行。此外,由于一个程序大部分时间都在执行其少数的代码,因此减少的编译时间是很重要的。最后,在最初的代码解释阶段,可以在编译前收集执行统计数据,这有助于进行更好的优化。

正确的权衡会因情况不同而不同。例如,Sun公司的Java虚拟机有两种主要模式--客户端和服务器。在客户端模式下,会进行最小的编译和优化,以减少启动时间在服务器模式下,会进行大量的编译和优化,通过牺牲启动时间,使应用程序运行后的性能最大化。其他的Java即时编译器使用方法执行次数的运行时间测量,结合方法的字节码大小作为启发式的决定何时编译。还有一个使用执行次数与循环的检测相结合。一般来说,在短时运行的应用程序中准确预测哪些方法需要优化比在长时运行的应用程序中更难。

微软的Native Image Generator(Ngen)是另一种减少初始延迟的方法。Ngen将通用中间语言(Common Intermediate Language, CIL) 镜像中的字节码预编译(或"预JIT")为机器本地代码。因此,不需要在运行时进行编译。与Visual Studio 2005一起携带的.NET框架2.0在安装后立即对所有的微软库DLLs运行Ngen。Pre-jitting提供了一种改善启动时间的方法。然而,它产生的代码质量可能不如JIT的代码,原因与静态编译的代码在没有剖析指导下的优化,在极端情况下不能像JIT编译的代码那样好的原因一样:缺乏剖析数据来驱动,例如,内联缓存。

也有一些Java实现将AOT(超前)编译器与JIT编译器(Excelsior JET)或解释器(GNU Compiler for Java)相结合

什么是超前预编译AOT

快速JIT

对于不包含循环且不可使用预编译代码的方法,快速JIT可以更快完成编译,但不会进行优化。

启用快速JIT会缩短启动时间,但可能会生成性能下降的代码。例如,代码可能会使用更多堆栈空间、分配更多内存并以更慢的速度运行。

如何开启快速JIT

方式一runtimeconfig.json

{
   "runtimeOptions": {
      "configProperties": {
         "System.Runtime.TieredCompilation.QuickJit": true
      }
   }
}

方式二*..csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TieredCompilationQuickJit>true</TieredCompilationQuickJit>
  </PropertyGroup>

</Project>

方式三,环境变量

COMPlus_TC_QuickJit=1
# 或者
DOTNET_TC_QuickJit=1

默认情况

  • 在NET Core 2.1和2.2中,默认禁用快速JIT
  • 在NET Core 3.0及更高版本中,默认启用快速JIT

包含循环的用法

改用System.Runtime.TieredCompilation.QuickJitForLoops

分层编译

分层编译会会将JIT实时编译器的方法拆成两个层级:

  • 第一层级,可以更快速地生成代码(快速JIT)或者加载预编译的代码(ReadyToRun)。
  • 第二层级,在后台生成优化的代码(优化JIT)。

如何开启分层编译

方式一runtimeconfig.json

{
   "runtimeOptions": {
      "configProperties": {
         "System.Runtime.TieredCompilation": true
      }
   }
}

方式二*..csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TieredCompilation>true</TieredCompilation>
  </PropertyGroup>

</Project>

方式三,环境变量

COMPlus_TieredCompilation=1
# 或者
DOTNET_TieredCompilation=1

参考

标签:字节,编译器,代码,跨平台,编译,JIT,Net,执行
From: https://www.cnblogs.com/taylorshi/p/16629071.html

相关文章