什么是 JIT

Python 是门多才多艺的语言,既可以写后端,也可以做数据分析,既可以智能化运维,也可以搞渗透,既可以写爬虫,又可以做机器学习深度学习。然而,Python 的缺点也很明显,它的速度有点慢。

我们从官方网站下载到的版本,默认是采用了 CPython 解释器,它也是用得最广的解释器。以 CPython 为例,看看它的执行过程。 Pyhton 代码(.py 文件)在运行时,解释器把源代码变为一组虚拟机指令,也就是“字节码”(.pyc 文件)。这些字节码指令,是运行在 Python 虚拟机上的。因为这些是运行在虚拟机的,自然而然就比 C/C++ 等可以编译为机器码的语言慢很多。当然,影响执行效率的因素还有很多,这里就不叙述。

django和python对应的版本 django pyc_django和python对应的版本

如果对高性能有非常迫切的需求,最好的解决方案是用 C/C++ 。不过,C/C++ 的学习难度比 Python 大很多,不是那么容易。除了换编程语言外,还有个更为容易的方法,那就是 JIT。

Just-In-Time(JIT),也就是即时编译,它为解释语言提供了一种优化。通俗地来说,就是代码在运行时,实时编译为机器码。这样,程序就可以跳过虚拟机直接在硬件上运行,执行速度大幅提高。

JIT 技术在 Java 中使用非常广泛。不过在 Python 中,以往 JIT 并不完善,听说过的人很少。

下面就介绍两种 Python 的解决方案。

Numba

Numba 是一个 开源的 JIT编译器,采用了 LLVM。它支持 Python 的原生函数和 Numpy,可以在 x86、x86_64、ppc64、armv7l、armv8l 等架构上运行,支持 Windows、MacOS 和 Linux。

Numba 的使用非常简单,无需更换 Python 的解释器。举一个简单的例子,只需要在函数上加上一个装饰器,Numba 就会自动将这些代码编译成机器码:

from numba import jit
import random
@jit(nopython=True)def monte_carlo_pi(nsamples):
acc = 0
for i in range(nsamples):
x = random.random()
y = random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
PyPy

PyPy 是 Armin Rigo开发的动态编译器,基于 Trace 的 JIT 技术,对源码进行动态编译(不是动态解释),可以显著提高执行速度。它历史非常悠久,1.0 版本在 2007 年发布。目前支持大多数标准库,在 Python 2.7 和 3.6 上都能使用。它可以在 x86、x86_64、ARMv6、ARMv7、AArch64PowerPC 64bit、System Z 等架构上运行,支持 Linux、MacOS、Windows、OpenBSD、FreeBSD 等系统。不过,在非 x86 架构上,它只能支持 Linux。

但它有个缺点,那就是不支持支持官方的 CPython,因而无法使用 Numpy、Scipy 等常用的重要第三方库。另外,PyPy 在使用上与 CPython有些不同,具体可看 https://doc.pypy.org/en/latest/cpython_differences.html ,需要注意。

总结

Python 的 JIT 技术还不是很完善,但 Numba 已经可以满足一大部分的计算需要。至于 PyPy,个人而言不太推荐。感兴趣的不妨试试 Numba。