来自Google 开源博客:
PyPy是Python的重新实现版本,使用先进技术,旨在比CPython具有更好的性能。多年的辛勤工作终于得到了回报。我们的速度结果通常击败CPython,从稍微慢一点,到实际应用代码加速2倍,甚至在小基准测试中加速高达10倍。
这怎么可能呢?是哪个Python实现版本用来实现PyPy的?CPython?那么,有没有机会让PyPyPy或PyPyPyPy超越它们的分数呢?
(另外...为什么会有人尝试这样做呢?)
来自Google 开源博客:
PyPy是Python的重新实现版本,使用先进技术,旨在比CPython具有更好的性能。多年的辛勤工作终于得到了回报。我们的速度结果通常击败CPython,从稍微慢一点,到实际应用代码加速2倍,甚至在小基准测试中加速高达10倍。
这怎么可能呢?是哪个Python实现版本用来实现PyPy的?CPython?那么,有没有机会让PyPyPy或PyPyPyPy超越它们的分数呢?
(另外...为什么会有人尝试这样做呢?)
"PyPy是Python在Python中的重新实现"这样描述PyPy是有点误导人,但从技术上讲确实如此。
PyPy有两个主要部分:
翻译框架是一个编译器。它将RPython代码编译成C(或其他目标),自动添加垃圾收集和JIT编译器等方面的内容。它不能处理任意的Python代码,只能处理RPython。
RPython是普通Python的一个子集;所有的RPython代码都是Python代码,但反过来不一定成立。没有关于RPython的正式定义,因为RPython基本上只是“可以由PyPy的翻译框架翻译的Python子集”。但是,为了能够进行翻译,RPython代码必须是静态类型的(类型是推断出来的,你不需要声明它们,但变量只能有一种类型),而且你也不能在运行时声明/修改函数/类等。
解释器是一个用RPython编写的普通Python解释器。
由于RPython代码是普通的Python代码,所以你可以在任何Python解释器上运行它。但是,PyPy的速度优势并不来自这种方式运行它;这只是为了进行快速测试循环,因为翻译解释器需要很长的时间。
了解了这些,就应该立即清楚关于PyPyPy或PyPyPyPy的猜测实际上没有任何意义。你有一个用RPython编写的解释器。你将其翻译成执行Python的C代码。这个过程到此为止;没有更多的RPython可以通过再次处理来加速。
因此,“PyPy如何比CPython更快”也变得相当明显。 PyPy有一个更好的实现,包括JIT编译器(我相信如果没有JIT编译器,它通常不会比较快,这意味着对于能够进行JIT编译的程序,PyPy才会更快)。CPython从未被设计为Python语言的高度优化实现(尽管他们确实试图使其成为高度优化的实现,如果你能理解这个区别的话)。
PyPy项目的真正创新之处在于,他们不手写复杂的 GC 方案或 JIT 编译器,而是使用 RPython 相对简单地编写解释器。虽然 RPython 比 Python 更低级,但它仍然是一种面向对象的垃圾回收语言,比 C 更高级。然后,翻译框架会自动添加 GC 和 JIT 等功能。因此,翻译框架是一个非常大的工作量,但它同样适用于 PyPy Python 解释器的任何实现方式,允许更自由地进行性能改进实验(无需担心引入 GC 错误或更新 JIT 编译器以适应变化)。这也意味着,当他们开始实现 Python3 解释器时,它将自动获得相同的优势。同时,所有使用 PyPy 框架编写的解释器(其中有许多处于不同阶段的完善)以及使用 PyPy 框架的解释器都自动支持框架支持的所有平台。Q1. 这是如何实现的?
手动内存管理(也就是CPython使用计数方法)在某些情况下可能比自动管理更慢。
CPython解释器实现上的限制阻碍了PyPy可以做的某些优化(例如细粒度锁定)。
像Marcelo所说的,这是通过JIT实现的。能够即时确认对象类型可以节省您不必要的多次指针反引用,最终到达您想要调用的方法。
Q2. PyPy使用了哪个Python实现进行实现?
PyPy解释器是用RPython实现的,它是Python的静态类型子集(语言而不是CPython解释器)。-有关详细信息,请参见https://pypy.readthedocs.org/en/latest/architecture.html。
Q3. PyPyPy或PyPyPyPy有打败其得分的机会吗?
这将取决于这些假设解释器的实现方式。如果其中一个解释器例如获取源代码,对其进行某种分析,并在一段时间后直接将其转换为紧密的目标特定汇编代码,我认为它将比CPython更快。
更新:最近,在精心制作的示例中,PyPy的性能超过了类似C程序使用gcc -O3
编译的程序。这是一个人为的情况,但确实展示了一些想法。
Q4. 为什么有人会尝试这样的事情?
来自官方网站。 https://pypy.readthedocs.org/en/latest/architecture.html#mission-statement
我们的目标是提供:
提供通用的翻译和支持框架,用于生成动态语言的实现,强调语言规范和实现方面之间的清晰分离。我们称之为
RPython工具链
_。一种符合标准、灵活且快速的Python_语言实现,它使用上述工具链,以便在不编码低级细节的情况下启用新的高级特性。
通过这种方式分离关注点,我们对Python和其他动态语言的实现能够自动生成任何动态语言的即时编译器。它还允许在实现决策方面进行混合和匹配,包括许多历史上超出用户控制范围的决策,例如目标平台、内存和线程模型、垃圾回收策略以及应用的优化,包括是否首先使用JIT。
像C编译器gcc一样是用C实现的,Haskell编译器GHC是用Haskell编写的。你有没有理由不用Python编写解释器/编译器呢?
PyPy是用Python实现的,但它使用JIT编译器即时生成本机代码。
实现PyPy在Python之上的原因可能是Python是一种非常高效的语言,特别是因为JIT编译器使得宿主语言的性能有些无关紧要。
PyPy使用Restricted Python编写,据我所知,它并不运行在CPython解释器之上。Restricted Python是Python语言的一个子集。据我所知,PyPy解释器被编译为机器码,因此安装后在运行时不需要利用Python解释器。
你的问题似乎期望PyPy解释器在执行代码时运行在CPython之上。 编辑:是的,要使用PyPy,您需要首先将PyPy Python代码翻译为C并使用gcc构建,或者翻译为jvm字节码,或者翻译为.Net CLI代码。请参见入门指南
gcc
。因此,你也可以编写一些在 CPython 上运行的 Python 代码,解释其他一些 Python 代码,将其转换为 C 代码,并执行gcc
,然后执行编译后的程序。如果代码被频繁调用,它可能会更快。 - Sergey Orshanskiy