事件回顾
就在不久前,Python核心开发者Pablo在邮件中宣布,由于一些重要的性能Bug和崩溃问题,预计在10月底发布的Python 3.11稳定版本可能要推迟到12月。
图片来源@邮件截图
此事引来了不少人的关注。Python是当今最流行的编程语言之一,StackOverflow 2022 开发者报告显示,对初学者而言,HTML/CSS、Javascript和Python几乎并列为最常用的语言,而在TIOBE发布的2022年6月编程语言排行上,Python语言则排名第一,因而Python语言新版本的发布,通常很受关注。
自2008年12月3日Python3.0发布以来,Python官方计划每年发布一个新版本,每次增加两三种新语法。虽然实际情况并没有严格按照计划实现,但自3.8版本以后,Python的发版节奏基本有规律可循:在每个版本发布前,都有17个月的开发周期,在此期间要进行持续的开发测试;测试期间,首先会发布alpha版本,等到4月份再发布beta版本,直到10月左右,发布最终的正式版本。Python 3历次版本发布时间
本来,计划今年发布的3.11版本也是按照这个节奏进行,但这次,3.11版本的发布会成为一个例外。值得一提的是,在邮件的最后,Pablo对能否在12月发布稳定版本也没有信心。
图片来源@邮件截图
Python 3.11期待已久
虽然Python简单易学,但其运行速度之慢历来被诟病(在每次的编程语言速度竞赛中,Python的名次通常都垫底),因而很多开发者期待这门语言的性能有所提升。
也许正是这个原因,Python创始人Guido van Rossum重新出山后,在2021年Python语言峰会上作了一场《Making CPython Faster》的分享,他表示,自己已经投入了“香农计划”(“Shannon Plan”,得名于提出者Mark Shannon),期望花4年时间把Python提速5倍,即每年1.5倍,其中近期计划是在Python 3.11 版本中实现至少提速1倍。
根据7月6日发布的Python 3.11.0b3来看,在Ubuntu Linux上使用GCC编译,且使用pyperformance基准套件测量时,CPython 3.11比CPython 3.10平均快25%。根据工作负载的不同,CPython 3.11的提速介于10% 到 60% 之间。
图片来源@文档截图
此外,由于Python3.11是一个较大版本更新,根据已有的测试结果看,其在更精确的错误提示、类型特性、用except*处理多个异常、Zero-cost异常、改进类型(包括改进类型、任意的字符串字面类型、数据类转换、标准库中的 TOML 只读支持等)也有改进,这些也是开发者比较期待的新功能。
如何给Python“踩踩油门”
此前Python为何会给大家留下运行速度慢的印象呢?通常有三种解释。
第一种解释为Python是动态性语言不是静态性语言。
对C等静态语言来说,编译器在声明变量的时候就知道其类型了;而对Python来说,Python程序在执行的时候,编译器不知道变量的类型,只知道它是一个对象。这意味着,即使是a+b这样的简单二元运算,由于变量a和b本身都没有类型,而它们的值有类型,Python执行起来也很“麻烦”:在相“加”之前,必须先判断类型。
第二种解释是Python是解释性语言而不是编译性语言。
像C、C++、Rust这些语言是直接编译成机器码运行,是编译型语言;Python的运行过程是虚拟机读入Python代码(文本),词法分析,编译成虚拟机认识的opcode,然后虚拟机解释opcode执行,而最后这一步“虚拟机解释opcode执行”是比较费时间的。
第三种解释认为,是全局解释器锁(GIL,Global Interpreter Lock)的原因。
现代计算机处理器一般都会有多核,甚至有些服务器有多个处理器。所以操作系统抽象出 Thread,可以在一个进程中spawn出多个Thread,让这些Thread在多个核上面同时运行,发挥处理器的最大效率。
而Python自带垃圾回收程序,且选择的实现垃圾回收机制是引用计数+分代回收,并以引用计数为主。在多线程情况下,大家一起运行,引用计数多个线程一起操作,为保证不发生线程不安全的事情,多个线程操作同一个对象需要加锁。这就是GIL,只不过这个锁的粒度太大了,整个Python解释器全局只有一个Thread可以运行。
换句话说,无论电脑CPU有多少核,对Python来说,它只用一个核。这三种解释都有一定道理,理论上Python提速可以从以上三个方向进行突破。从最近Python团队公布的情况看,Python 3.11 的性能改进主要集中在更快的启动和更快的运行时,这些优化大部分来自于PEP 659(一种自适应解释器),它运作思路跟JIT有点相似,都是识别热点代码,但自适应解释器的工作范围无法脱离字节码。
图片来源@文档截图
3.11为何会推迟发布
从Pablo在邮件中公布的信息看,Python 3.11推迟发布主要是由于出现很多“影响发布”的bug。
图片来源@GitHub截图
虽然bug的细节还有待进一步发掘,但根据现有情况猜测,问题可能在以下的两方面。
一是C扩展的问题。CPython与C的简单接口是主要优势,而与C扩展的不兼容性则是一大槽点。CPython团队在CPython 3.11中所做的优化工作在很大程度上忽略了扩展模块的问题,对此,团队领导者香农表示,团队正在开辟将低级函数API暴露给虚拟机的可能性,以尽可能地减少Python代码和C代码。
二是前面反复提到的提速问题。Python创始人Guido van Rossum预期Python 3.11版本中实现至少提速1倍,而目前Python 3.11.0b3比Python 3.10平均只快了25%,跟理想目标还有不小的差距。
另外,Meta开发人员Sam Gross在今年的Python语言峰会上,向与会者介绍了nogil的情况,这是一个专注于移除GIL的项目,据Python基金会介绍,Gross 将发明一种新型锁,如果顺利的话,这个新锁很可能在Python 3.12版本亮相。
Sam Gross的提案虽然让很多开发者兴奋,但与Python团队的现在工作基于PEP 659进行优化的工作会产生冲突:毕竟CPython团队已实施的优化,很大一部分都基于GIL仍存在的前提。如果采用Sam Gross的提案,在Python 3.12去除GIL,那么Python 3.11就要做出不小的改动,也许,这也是导致Python 3.11延期的重要原因。
总之,考虑到当前Python在编程语言界“如日中天”的地位,Python 3.11又志在克服其最大的缺点,Python的未来还是很值得期待的。
参考链接:
https://mail.python.org/archives/list/python-dev@python.org/thread/3JWVCSBPBFWY5ZWSJ7RYB6FS5NIMCEOY/
https://docs.python.org/zh-cn/3.11/whatsnew/3.11.html#faster-cpython