问题描述
微软Pyjion自项目开始以来时间不长,但是Github上已经有两个月没有任何提交,不知道是不是已经挂了。在Perf目录下的README.md文件里有最新的benchmarks结果,显示加了jit后,很多benchmark性能反而下降了,有的甚至慢4倍以上。在Unladen Swallow, Psyco, Pyjion(?)等等项目的众多大牛们对CPython JIT的尝试均告失败后,我们究竟应该如何看待CPython性能优化的未来?
Pyjion还没死。Brett和Dino大大本来开Pyjion项目就是自己在业余时间搞的,而不是微软正式立项全力支持的项目,所以他俩一忙正经工作就不得不减少对Pyjion的投入这个是最初大家都知道的事。
背景介绍:
[新闻] CPython / 微软 Pyjion / IBM Python+OMR - 编程语言与高级语言虚拟机杂谈(仮) - 知乎专栏他们现在最关注的是
PEP 523 -- Adding a frame evaluation API to CPython。这其实才是Pyjion对CPython影响最大的部分,是Pyjion项目最核心的目标——给CPython添加API,让它支持插入JIT编译器。
Pyjion的目标:
- Add a C API to CPython for plugging in a JIT
- Develop a JIT module using CoreCLR utilizing the C API mentioned in goal #1
- Develop a C++ framework that any JIT targetting the API in goal #1 can use to make development easier
这里面#1是最重要的,而#2目前的形态只是为了验证#1的效果,并且有一个实际实现来说服CPython社区这是现实可行的而不是空想。
PEP 523就是目标#1目前的形态。Brett和Dino在与CPython社区以及其它Python实现团队讨论之后,发现他们原本想提议的那个JIT编译器API太具体了,限制了应用场景,感兴趣的人不多;同时他们发现其实只要一个更简单的钩子就足以让JIT编译器能挂进来,这也就是现在的PEP 523。
原本目标#1所想像的API的一部分会挪到目标#3里去,作为可插入的JIT编译器的框架的一部分,而不是作为CPython内建的一部分。
Pyjion目前的实现还非常简单,特别是在触发编译的地方做得还很粗糙。这块正是非常影响JIT编译器对整体运行性能的地方。JIT编译毕竟是一个运行时行为,有相应的开销,如果一个程序运行的时间太短,则JIT编译带来的性能提升可能无法弥补其所带来的开销,总体结果就是变得更慢了。
在其它成熟的托管运行时上,这种问题有许多现成的解决方案。至少,要解决题主说的“加了JIT比不加还慢”的问题是有很现成的做法的。
其一是后台编译(background compilation),允许解释器在触发编译后继续解释执行程序,而被触发的JIT编译则在后台并发编译,这样就可以最大限度减少JIT编译对程序的初始性能的负面影响。Pyjion目前的实现用的是阻塞式前台编译(blocking compilation / foreground compilation),也就是当解释器触发JIT编译后,解释器要停下来等,直到JIT编译完成后再跳到编译好的代码里去执行。这对许多小程序来说都太慢了。
其二是多层编译(tiered compilation),让代码随着被执行次数的增加2而渐渐被更高优化层级的编译器所编译。Pyjion目前只有解释器和一级JIT编译器,所有JIT编译都用同样的优化层级,对只执行比较少次数的代码来说可能会带来过多的编译开销,而对执行次数很多的代码来说可能没有投入足够编译优化。
其三是并行编译(parallel compilation),开多个线程来同时并行编译多个函数。
以成熟的JVM——HotSpot VM为例,上述3种技巧都用上了,效果很好。
顺带放个传送门吧:
为什么 JVM 不用 JIT 全程编译? - RednaxelaFX 的回答这些都是属于Pyjion的目标#2的问题。上面也说了,Pyjion目前的目标#2其实只是玩票性质的,并不是他们想要做的最终形态。它目前存在的目的就是告诉大家这个JIT是真的可行的,是完全兼容CPython 3.5的,并且在一些运行时间较长的场景里能展现出性能提升。
要提升它的启动性能,只要投入开发资源去打磨打磨JIT的触发方式就能看到显著效果,只是目前暂时还没到那一步而已。
(思路之一:让一个Python函数执行多次(例如10次、100次)之后再触发JIT编译,并且支持后台编译与并行编译)
=======================================
至于题主问的:
在Unladen Swallow, Psyco, Pyjion(?)等等项目的众多大牛们对CPython JIT的尝试均告失败后,我们究竟应该如何看待CPython性能优化的未来?
这个回头再补充…但一言以蔽之:受制于CPython所坚持要保持兼容的C API,CPython的性能优化的天花板太低了。添加JIT编译器能够提升性能,但提升空间非常有限,因为runtime里的额外开销太多了。
放个传送门占位:
Pyjion的代码质量一例 [20160221] - 编程语言与高级语言虚拟机杂谈(仮) - 知乎专栏=======================================
有别的回答提到Dropbox的Pyston。这个项目其实现在处于很微妙的状态…(咳咳
正好我以前的经理现在在Dropbox做经理,也会管到Pyston,最近跟他聊的时候听说他们在考虑大幅改变Pyston的开发方向。不知道最后能不能招到人去做这件事呢。
技术问题除外,Pyston要面临的最大问题恐怕就是随着Dropbox越来越多代码转为用Go实现,优化Python自身性能的迫切性越来越低了。而优化Go的性能变成了新的热点。如何分配开发资源就成了个有趣的问题。——一手小道消息。