Optimization JIT编译器可以做哪些AOT编译器不能做的事情?

Optimization JIT编译器可以做哪些AOT编译器不能做的事情?,optimization,compiler-construction,compiler-optimization,jit,Optimization,Compiler Construction,Compiler Optimization,Jit,即时(JIT)编译器可以基于对提前(AOT)编译器不可用的运行时信息优化程序 此运行时信息的最明显示例是目标平台,例如,运行程序的确切CPU,或任何可用的加速器,如GPU。这就是OpenCL JIT编译的意义 但是,假设我们提前知道目标平台是什么:我们知道哪些SIMD扩展将可用,等等。JIT编译器可以利用哪些AOT编译器无法利用的其他运行时信息 热点风格的JIT编译器将自动优化程序的热点。。。但是AOT编译器不能只优化整个程序、热点和所有方面吗 我想要一些JIT编译器可以执行AOT编译器无法执行

即时(JIT)编译器可以基于对提前(AOT)编译器不可用的运行时信息优化程序

此运行时信息的最明显示例是目标平台,例如,运行程序的确切CPU,或任何可用的加速器,如GPU。这就是OpenCL JIT编译的意义

但是,假设我们提前知道目标平台是什么:我们知道哪些SIMD扩展将可用,等等。JIT编译器可以利用哪些AOT编译器无法利用的其他运行时信息

热点风格的JIT编译器将自动优化程序的热点。。。但是AOT编译器不能只优化整个程序、热点和所有方面吗


我想要一些JIT编译器可以执行AOT编译器无法执行的特定优化的示例。如果您能提供任何证据证明这种优化在“真实世界”场景中的有效性,您将获得额外的好处。

一个优点是JIT编译器可以连续分析代码并优化输出,例如对齐/取消对齐某些代码块、取消优化某些函数、重新排序分支以减少预测失误

当然,AoT编译器也可以进行概要文件引导的优化,但是它们在开发人员和测试人员执行的测试用例中受到限制,这可能无法反映实际输入的动态特性

例如,Android在Kitkat中引入了ART,而在Nougat和更高版本中采用了混合方法。在Nougat和更高版本中,应用程序的某些部分提前编译,优化程度较低,然后在运行配置文件后,在手机充电时,将使用配置文件结果再次优化应用程序

Android 7.0 Nougat向ART引入了带有代码分析的JIT编译器,使其能够在Android应用程序运行时不断提高性能。JIT编译器补充了ART当前的超前编译器,并有助于提高运行时性能。[9]

一些相关问题:

JIT编译器可以做哪些AOT编译器不能做的事情

在理论上;没有,因为AOT编译器可以在需要时将JIT编译器插入到生成的代码中(和/或可以生成自修改代码,生成123个替代版本,并根据运行时信息选择要使用的版本,…)

在实践中;AOT编译器受到编译器设计者想要处理的复杂性、编译语言以及编译器使用方式的限制。例如,一些编译器(英特尔的ICC)将生成多个版本的代码,并(在运行时)根据它运行在哪个CPU上决定使用哪个版本,但大多数编译器并不是专门为此设计的;许多语言不提供任何控制“局部性”的方法(并减少TLB未命中和缓存未命中的机会);通常,编译器的使用方式会造成阻碍优化的障碍(例如,单独的“编译单元”/稍后链接在一起的对象文件,可能包括动态链接,其中AOT编译器不可能进行整个程序优化,只能单独优化部分)。所有这些都是实现细节,而不是AOT的限制


换言之;实际上,“AOT与JIT”是实现的比较,而不是“AOT与JIT”本身的真正比较;在实践中,由于实现细节的原因,AOT的性能很差,而JIT的性能明显比差,因为JIT本身很差(昂贵的优化根本不可行,因为它们是在运行时进行的);JIT看起来“几乎一样好”的唯一原因是它“几乎一样坏”。

JIT可以基于运行时信息进行优化,这会导致在编译时无法证明的更严格的边界条件。示例:

  • 它可以看到内存位置没有别名(因为所采用的代码路径从未对其进行别名化),因此将变量保留在寄存器中
  • 它可以消除永远不会发生的条件下的测试(例如,基于参数的当前值)
  • 它可以访问完整的程序,并可以在它认为合适的地方内联代码
  • 它可以在运行时根据特定的使用模式执行分支预测,从而达到最佳效果
内联主要也适用于现代编译器/链接器的链接时间优化,但如果只是为了以防万一而在整个代码中应用,可能会导致禁止性的代码膨胀;在运行时,它可以在需要的地方应用

如果程序被编译两次,并且中间有一次测试运行,则使用普通编译器可以改进分支预测;在第一次运行中,对代码进行检测,以便生成分析数据,该数据用于生产编译运行,以优化分支预测。如果测试运行不是典型的(并且生成典型的测试数据并不总是容易的,或者使用模式可能会随着程序的生命周期而改变),那么预测也不是最优的


此外,静态编译的链接时和运行时数据优化都需要在构建过程中付出巨大的努力(在我一生中工作过的10多个地方,我还没有看到它们在生产中得到应用);使用JIT时,默认情况下它们处于启用状态

你读过吗:@AnubhavSrivastava谢谢你的链接。这是一个类似的问题,但无论是评分最高的答案还是公认的答案都没有真正回答我的问题。不过,在其他答案中有几个仅JIT优化的例子:跨库优化和使用跟踪树的动态内联。我很想知道它们在实践中有多大的不同。反射是一个臭名昭著的问题,不能静态地确定需要哪种类型