PyPy 使用什么类型的 JIT编译器?真正的一个(整个代码是在app启动时翻译的)还是经济的一个(只编译过的部分)?
答案 0 :(得分:4)
根据this blog post,它是一个跟踪jit编译器;
此时值得一读的是如何跟踪JIT编译器的工作方式。这里有一个简短的解释:解释器通常运行你的解释器代码。当它检测到目标语言中的代码循环经常被执行时,该循环被认为是“热”并被标记为被跟踪。下次进入该循环时,解释器将进入跟踪模式,其中记录每条执行的指令。
循环结束后,跟踪停止。循环的跟踪被发送到优化器,然后发送到输出机器代码的汇编器。然后,该机器代码用于后续循环迭代。
此机器代码通常针对最常见的情况进行优化,并且取决于对代码的若干假设。因此,机器代码将包含警卫,以验证这些假设。如果防护检查失败,则运行时会回退到常规解释模式。
答案 1 :(得分:1)
正如Roland Smith的回答所述,PyPy使用了一种跟踪JIT编译器的形式。跟踪JIT仅根据定义编译“使用过的部分” 。
请注意,这并不比通过在启动期间编译整个程序开始的假设JIT更少真实。实际上,有几个很好的理由可以避免这种策略。
启动可能会变得非常慢,因为编译器必须处理整个程序,即使它的很大一部分可能永远不会被执行。无论JIT是从源代码还是从字节码开始,都是如此。
许多编程语言 - 特别是动态语言,例如JavaScript - 可以从能够适应程序运行时属性的编译器中获益匪浅。强制JIT在启动时编译所有内容往往会排除有趣的优化,这些优化依赖于访问,比如输入在运行时收集的信息。
听起来你对“真实与经济”的分歧可能源于对方法JIT 与追踪JIT 之间区别的误解。
在方法JIT中,例如Oracle的HotSpot,编译单元是方法(或函数,或过程,或任何你想要调用的方法)。这是AOT compilers传承的传统。方法JIT严重依赖inlining向优化器公开更多代码。在实际调用方法之前,方法JIT推迟编译方法并不罕见。
相比之下,跟踪JIT会在程序运行时观察并记录实际执行的指令序列(通常是某种bytecode)。与必须明确选择内联方法调用的方法JIT不同,内联是具有跟踪JIT的便利副作用。就像JIT方法可以推迟编译方法一样,跟踪JIT通常会在将跟踪编译为机器代码之前等待一些执行计数阈值,否则会浪费宝贵的时间来编译永远不会再运行的跟踪(例如在main
开头运行一次的热循环!)。
请注意,上述简要说明大大简化;如果你对这个主题感兴趣,我鼓励你更详细地研究两种JIT策略。