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