为什么JIT代码比编译代码或解释代码消耗更多内存?

Con*_*ion 7 compiler-construction jit programming-languages pypy

编译代码如C消耗很少的内存.

解释代码如Python消耗更多内存,这是可以理解的.

使用JIT,程序在运行时(有选择地)编译为机器代码.那么JIT的程序的内存消耗应该介于编译程序和解释程序之间吗?

相反,JIT的程序(例如PyPy)消耗的内存比等效的解释程序(例如Python)多几倍.为什么?

Nec*_*lis 8

跟踪JIT编译器需要占用更多内存,因为它们不仅需要保留VM的字节码,还需要保留直接可执行的机器代码.然而,这只是故事的一半.

大多数JIT还会保留很多关于字节码(甚至机器代码)的元数据,以便他们确定需要JIT的内容以及可以单独使用的内容.跟踪JIT(例如LuaJIT)还会创建跟踪快照,用于在运行时微调代码,执行循环展开或分支重新排序等操作.

有些还保留了常用代码段或快速查找缓冲区的缓存,以加速JIT代码的创建(LuaJIT通过DynAsm实现这一点,它实际上可以帮助减少正确完成时的内存使用,就像dynasm一样).

内存使用很大程度上取决于所使用的JIT引擎及其编译语言的性质(强与弱类型).一些JIT采用先进的技术,如基于SSA的寄存器分配器和变量生动性分析,这些优化也有助于消耗内存,以及更常见的事情,如循环变量提升.


Ben*_*Ben 5

你要说的是什么的内存使用要小心.

编译为C的代码编译的机器代码本身使用相对较少的内存.

我希望给定算法的Python字节码实际上小于类似算法的编译C代码,因为Python字节码操作要高得多,所以通常用较少的字节码来完成给定的事情.但是Python程序也会在内存中包含Python解释器的编译代码,这本身就是一个庞大而复杂的程序.另外一个典型的Python程序在内存中将拥有比典型的C程序更多的标准库(如果它是静态链接的话,C程序可以删除它实际上不使用的所有函数,如果它是动态链接的,那么它共享已编译的代码与内存中使用它的任何其他进程).

然后PyPy在此基础上有JIT编译器的机器代码,以及从Python字节码生成的机器代码(它不会消失,它也必须保持不变).因此,你的直觉(JITed系统"应该"在编译语言和完全解释语言之间的某处消耗内存)无论如何都是不正确的.

但除了所有这些之外,您还拥有程序运行的数据结构所使用的实际内存.这种情况变化很大,与程序是提前编译,还是解释,解释和JIT编辑无关.一些编译器优化将减少内存使用(无论是提前应用还是只是及时应用),但许多实际上会牺牲内存使用来提高速度.对于操纵任何大量数据的程序,无论如何它将使代码本身使用的内存完全相形见绌.

当你说:

相反,JIT的程序(如PyPy)消耗的内存比等效的解释程序(如Python)多几倍.为什么?

你在想什么课程?如果你真的做了任何比较,我猜你的问题是他们将在PyPy和CPython之间.我知道PyPy的许多数据结构实际上比CPython小,但同样,这与JIT无关.

如果程序的主要内存使用是代码本身,那么JIT编译器会增加巨大的内存开销(对于编译器本身和编译的代码),并且根本无法通过"赢回"内存使用量来实现优化.如果占主导地位的内存使用是程序数据结构,那么无论是否启用JIT,我都不会惊讶地发现PyPy使用的内存比CPython少得多.


你的"为什么?"真的没有一个直截了当的答案.因为你问题中的陈述不是直截了当的.哪个系统使用更多内存取决于许多因素; JIT编译器的存在与否是一个因素,但并不总是重要的.