PyPy 使用什么样的 JIT 编译器?
What kind of JIT compiler is used by PyPy?
PyPy 使用什么样的 JIT 编译器?
- tracing JIT or something like Java HotSpot Virtual Machine.
- 每个方法调用种类。
- 类似于 .NET Framework 的 Econo JIT Compiler。
根据this blog post,它是一个跟踪 jit 编译器;
It's worth it at this point to read up on how tracing JIT compilers work. Here's a brief explanation: The interpreter is usually running your interpreter code as written. When it detects a loop of code in the target language is executed often, that loop is considered "hot" and marked to be traced. The next time that loop is entered, the interpreter gets put in tracing mode where every executed instruction is logged.
When the loop is finished, tracing stops. The trace of the loop is sent to an optimizer, and then to an assembler which outputs machine code. That machine code is then used for subsequent loop iterations.
This machine code is often optimized for the most common case, and depends on several assumptions about the code. Therefore, the machine code will contain guards, to validate those assumptions. If a guard check fails, the runtime falls back to regular interpreted mode.
如 Roland Smith 的回答所述,PyPy 使用一种跟踪 JIT 编译器的形式。根据定义.
,跟踪 JIT 仅编译 "used parts"
请注意,这并不比在启动期间通过编译整个程序开始的一些假设的 JIT 更不 真实。事实上,有几个很好的理由可以避免这种策略。
启动时间
启动可能会变得非常慢,因为编译器必须处理整个程序,即使其中很大一部分可能永远不会执行。无论 JIT 是从源代码还是字节码开始都是如此。
失去优化机会
许多编程语言——特别是动态语言,例如JavaScript——可以从能够适应程序运行的编译器中获益匪浅时间属性。强制 JIT 在启动时编译所有内容往往会排除依赖于访问的有趣优化,比如说,在 运行 时间收集的类型信息。
听起来您对 "real vs economic" 的区分可能源于对 方法 JIT 和 跟踪 JIT[=40] 之间区别的误解=].
在方法 JIT 中,例如 Oracle 的 HotSpot,编译的单位是方法(或函数,或过程,或任何你想调用它的东西)。这是从 AOT compilers. Method JIT's rely heavily on inlining 继承下来的传统,将更多代码暴露给优化器。方法 JIT 将方法的编译推迟到实际调用时并不罕见。
相比之下,跟踪 JIT 观察并记录 实际执行 的指令序列(通常是某种 bytecode)作为程序 运行s。与必须显式选择内联方法调用的方法 JIT 不同,内联是具有跟踪 JIT 的一个方便的副作用。就像方法 JIT 可以延迟方法的编译一样,跟踪 JIT 通常会在将跟踪编译为机器代码之前等待某个执行计数阈值,否则它可能会浪费宝贵的时间来编译永远不会 运行 的跟踪再次(例如 运行 在 main
的开头出现一次的热循环!)。
请注意,上面的简要说明已大大简化;如果您对该主题感兴趣,我鼓励您更详细地研究这两种 JIT 策略。
PyPy 使用什么样的 JIT 编译器?
- tracing JIT or something like Java HotSpot Virtual Machine.
- 每个方法调用种类。
- 类似于 .NET Framework 的 Econo JIT Compiler。
根据this blog post,它是一个跟踪 jit 编译器;
It's worth it at this point to read up on how tracing JIT compilers work. Here's a brief explanation: The interpreter is usually running your interpreter code as written. When it detects a loop of code in the target language is executed often, that loop is considered "hot" and marked to be traced. The next time that loop is entered, the interpreter gets put in tracing mode where every executed instruction is logged.
When the loop is finished, tracing stops. The trace of the loop is sent to an optimizer, and then to an assembler which outputs machine code. That machine code is then used for subsequent loop iterations.
This machine code is often optimized for the most common case, and depends on several assumptions about the code. Therefore, the machine code will contain guards, to validate those assumptions. If a guard check fails, the runtime falls back to regular interpreted mode.
如 Roland Smith 的回答所述,PyPy 使用一种跟踪 JIT 编译器的形式。根据定义.
,跟踪 JIT 仅编译 "used parts"请注意,这并不比在启动期间通过编译整个程序开始的一些假设的 JIT 更不 真实。事实上,有几个很好的理由可以避免这种策略。
启动时间
启动可能会变得非常慢,因为编译器必须处理整个程序,即使其中很大一部分可能永远不会执行。无论 JIT 是从源代码还是字节码开始都是如此。
失去优化机会
许多编程语言——特别是动态语言,例如JavaScript——可以从能够适应程序运行的编译器中获益匪浅时间属性。强制 JIT 在启动时编译所有内容往往会排除依赖于访问的有趣优化,比如说,在 运行 时间收集的类型信息。
听起来您对 "real vs economic" 的区分可能源于对 方法 JIT 和 跟踪 JIT[=40] 之间区别的误解=].
在方法 JIT 中,例如 Oracle 的 HotSpot,编译的单位是方法(或函数,或过程,或任何你想调用它的东西)。这是从 AOT compilers. Method JIT's rely heavily on inlining 继承下来的传统,将更多代码暴露给优化器。方法 JIT 将方法的编译推迟到实际调用时并不罕见。
相比之下,跟踪 JIT 观察并记录 实际执行 的指令序列(通常是某种 bytecode)作为程序 运行s。与必须显式选择内联方法调用的方法 JIT 不同,内联是具有跟踪 JIT 的一个方便的副作用。就像方法 JIT 可以延迟方法的编译一样,跟踪 JIT 通常会在将跟踪编译为机器代码之前等待某个执行计数阈值,否则它可能会浪费宝贵的时间来编译永远不会 运行 的跟踪再次(例如 运行 在 main
的开头出现一次的热循环!)。
请注意,上面的简要说明已大大简化;如果您对该主题感兴趣,我鼓励您更详细地研究这两种 JIT 策略。