LLVM、Parrot、JVM、PyPy + Python
在开发一些编程语言时,比如说 Python,使用一些优化技术和 LLVM 或 Parrot 会遇到什么问题呢?
PyPy、LLVM 和 Parrot 是开发通用平台的主要技术。
我把它们理解为:
- PyPy - 是一个用来构建虚拟机的框架,里面有为 Python 优化的虚拟机。
所以这算是一个比较通用的解决方案。整个过程可以分为以下几个步骤:
- 动态语言代码 ->
- PyPy 前端 ->
- PyPy 内部代码 - 字节码 ->
- PyPy 优化 ->
- 生成 PyPy 代码,然后:
a. PyPy 后端用于某个虚拟机(比如 JVM)
b. 一些工具包用来创建自己的虚拟机
c. 处理/运行 PyPy 内部代码
- 动态语言代码 ->
我对这个过程理解得对吗?对于 Python 来说,有优化过的虚拟机吗?特别是默认情况下,PyPy 代码(步骤 5.c)有一个内置的优化虚拟机,这个虚拟机是为 Python 设计的,每种语言的处理都可以在这里停止并运行吗?
- Parrot - 和 PyPy 很像,但没有步骤 5.a 和 5.b?它有一些内部改进,用于动态处理(Parrot 魔法饼干)。
Parrot 和 PyPy 都是为了创建一个可以运行动态语言的平台,但 PyPy 想要更多 - 还想创建更多的虚拟机。
那么 PyPy 的意义在哪里呢?我们为什么需要创建更多的虚拟机?难道不应该像 Parrot 那样专注于一个虚拟机吗?因为无论是 PyPy 的内部字节码还是 Parrot 的字节码,都是在同一个代码层面上。我觉得把 PyPy 的字节码转换成用 PyPy 创建的新虚拟机的字节码并没有什么好处。
- LLVM - 我觉得它和 PyPy 很相似,但没有虚拟机生成器。
它是一个成熟、设计良好的环境,目标和 PyPy 类似(但没有虚拟机生成器),但它在低级结构和优化/即时编译技术方面做得很好。
我认为:LLVM 是通用的,而 Parrot 和 PyPy 是专为动态语言设计的。在 PyPy 和 Parrot 中,引入一些复杂技术会更容易,因为它们的层次更高,像是一个复杂的编译器,可以更好地理解高级代码并生成更好的汇编代码(人类在合理的时间内无法编写),而 LLVM 则不一定能做到这一点。
问题:
我理解得对吗?有没有理由认为将某种动态语言移植到 LLVM 比移植到 Parrot 更好呢?
我没有看到在 Parrot 上开发 Python 的活动。是因为使用 Python 的 C 扩展在 Parrot 上无法工作吗?在 PyPy 上也是同样的问题。
为什么其他虚拟机不想转向 LLVM 或 Parrot?比如说 Ruby 转向 Parrot,CLR/JVM 转向 LLVM。对它们来说,转向更复杂的解决方案不是更好吗?LLVM 正在快速发展,并且有大公司在投资。
我知道问题可能出在重新编译的资源上,如果需要更改字节码,但这并不是强制性的 - 因为我们可以尝试将旧字节码移植到新字节码,而新的编译器会生成新的字节码(尽管 Java 仍然需要解释自己的字节码 - 这样前端可以检查并将其转换为新字节码)?
如果我们以某种方式将 Java/JVM/Scala 移植到 LLVM,链接 JVM 库会有什么问题?
如果我哪里错了,请纠正我。
补充说明:
=============
澄清一下
我想弄清楚这些软件是如何构成的,以及将它们移植到其他平台时会遇到什么问题。
3 个回答
主要原因是什么呢?因为虚拟机(VM)的设计还没有一个固定的标准,拥有多种不同目标和用途的虚拟机,可以让我们同时尝试多种不同的方法,而不是一个接一个地试。
像JVM、CLR、PyPy、Parrot、LLVM等,都是以不同的方式解决不同类型的问题。这就像Chrome、Firefox、Safari和IE各自使用自己的JavaScript引擎一样。
Unladen Swallow这个项目试图把LLVM应用到CPython上,但他们花在修复LLVM问题上的时间,比专注于Python特定问题的时间还要多。
Python-on-Parrot项目因为Perl 6和Python之间的语义差异,导致前端编译过程出现问题,所以未来在这方面的努力可能会使用PyPy的前端来针对Parrot虚拟机。
不同的虚拟机开发者当然会关注其他人的进展,但即使他们借鉴了好的想法,也会在此基础上进行改进,加入自己的特色。
你想实现什么呢?你的问题表达得有点混乱(我知道英语可能不是你的母语)。
LLVM和PyPy都是成熟且有用的项目,但目前它们之间的重叠不多。(曾经,PyPy可以生成LLVM字节码——这是一种静态编译到解释器的方式,而不是生成C代码,但这并没有带来太大的性能提升,现在也不再支持了。)
PyPy允许你用RPython编写一个解释器,并用这个解释器的描述来生成本地代码的解释器或即时编译器(JIT);而LLVM是一个用C++构建编译工具链的框架,也可以用来实现JIT。LLVM的优化器、代码生成和平台支持比PyPy要先进得多,但它不太适合构建动态语言的运行时(可以参考Unladen Swallow的回顾,里面有一些例子说明原因)。特别是,LLVM在收集和使用运行时反馈方面不如PyPy的基于跟踪的JIT有效,而这些反馈对于让动态语言表现良好是非常重要的。此外,LLVM的垃圾回收支持仍然有些原始,缺乏PyPy自动生成JIT的独特能力。
顺便提一下,有两个Java实现是基于LLVM的——J3/VMKit和Shark。
你可以考虑观看上周斯坦福大学的PyPy讲座;它提供了一个关于PyPy工作原理的不错概述。Carl Friedrich Bolz的演示文稿也很好地概述了虚拟机实现的现状。
这个问题在StackOverflow上可能没人能回答,但我试着简单说一下。
首先,这三个项目解决了什么问题呢?
pypy让你可以用高级语言来实现一个解释器,并且你可以免费获得一个生成的JIT(即时编译器)。这点很不错,因为这样你就不需要担心语言和平台之间的依赖问题。这也是为什么pypy-clr比IronPython快的原因。更多信息可以查看这里:http://codespeak.net/pypy/dist/pypy/doc/extradoc.html --> 这是一个为CLI/.NET提供高性能Python实现的项目,支持动态的JIT编译。
llvm是一个为编译器提供的低级基础设施。它的基本思想是有一种“高级汇编语言”。所有的优化都是基于这种语言进行的。然后有很多工具可以帮助你构建编译器(无论是JIT还是AOT)。在llvm上实现动态语言是可行的,但比在pypy或parrot上需要更多的工作。例如,你不能免费获得垃圾回收(GC),虽然有一些GC可以和LLVM一起使用,具体可以参考这里:http://llvm.org/devmtg/2009-10/ --> vmkit视频)。目前也有一些尝试在llvm基础上构建更适合动态语言的平台:http://www.ffconsultancy.com/ocaml/hlvm/
我对parrot了解不多,但据我所知,他们想建立一个专门为动态语言(如perl、php、python等)设计的标准虚拟机。这里的问题和编译到JVM/CLR时一样,都是依赖不匹配,只是小得多。这个虚拟机仍然不知道你的语言的语义。根据我的理解,parrot在用户代码的执行上还是比较慢的。(http://confreaks.net/videos/118-elcamp2010-parrot)
关于你的问题:
我说得对吗?把某些动态语言移植到llvm上比移植到parrot上更有理由吗?
这取决于付出的努力。自己构建一切并为自己量身定制最终会更快,但这需要付出很多努力。
我没有看到在Parrot上开发Python的活动。是因为使用Python的C扩展在Parrot上不工作吗?PyPy也有同样的问题。
目前针对parrot的开发(在这个阶段)不太可能比pypy有更多的好处。我不知道为什么其他人不这样做。
为什么其他虚拟机不想转向LLVM或parrot。例如,ruby转向parrot,CLR/JVM转向LLVM。对他们来说,转向更复杂的解决方案不是更好吗?LLVM正在快速发展,并且有大公司在投资。
这个问题包含很多内容。
- 正如我所说,转向LLVM是很困难的,而parrot的速度也不快(如果我错了请纠正我)。
- Ruby有Rubinius,它尝试在Ruby中做很多事情,并将JIT编译到llvm上(http://llvm.org/devmtg/2009-10/ --> 用LLVM加速Ruby)。
- 在LLVM上有CLR/JVM的实现,但它们已经有非常成熟的实现,并且投入了大量资金。
- LLVM并不是高级的。
我知道问题可能出在重新编译的资源上,如果需要更改字节码,但这并不是强制的——我们可以尝试将旧字节码移植到新字节码,而新的编译器会生成新的字节码(尽管Java仍然需要解释自己的字节码,以便前端可以检查并将其转换为新的字节码)?
我不知道这个问题是什么。
如果我们以某种方式将Java/JVM/Scala移植到LLVM,链接JVM库会有什么问题?
看看我上面提到的VMKit视频,看看他们取得了多大进展以及遇到了什么问题(以及他们是如何解决的)。
如果我哪里错了,请纠正我。
你写的很多内容是错误的,或者我根本不理解你的意思,但我提供的链接应该能让很多事情变得更清楚。
一些例子:
Clojure
创建者不想花所有的精力去实现自己的虚拟机和所有的库。那么该去哪里呢?由于Clojure是一种新语言,你可以通过限制很多动态特性来使其在像JVM这样的平台上运行得很好,而这些特性在Python或Ruby中是常见的。
Python
这种语言(Python)实际上无法更改以便在JVM/CLR上运行得很好。因此,在这些平台上实现Python不会带来巨大的速度提升。静态编译器也不太好用,因为没有很多静态保证。用C编写JIT会很快,但很难修改(参见psyco项目)。使用llvm的JIT可能可行,并且正在被Unladen Swallow项目探索(再次参考:http://llvm.org/devmtg/2009-10/ --> Unladen Swallow: Python on LLVM)。一些人想要在Python中实现Python,所以他们开始了pypy,他们的想法似乎运作得很好(见上文)。Parrot也可能可行,但我还没看到有人尝试过(欢迎尝试)。
关于一切:
我觉得你可能有些困惑,我能理解。慢慢来,阅读、倾听、观看你能找到的所有资料。不要给自己太大压力。这其中有很多部分,最终你会看到这些部分是如何结合在一起的,什么是有意义的。即使你知道很多,仍然有很多讨论可以进行。关于在哪里实现新语言或如何加速旧语言的问题有很多答案,如果你问三个人,你可能会得到三个不同的答案。