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

时间:2011-12-30 02:08:20

标签: compiler-construction programming-languages jit pypy

C等编译代码消耗的内存很少。

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

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

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

2 个答案:

答案 0 :(得分:8)

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

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

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

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

答案 1 :(得分: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编译器的存在与否是一个因素,但并不总是很重要。

相关问题