近日,开发者 Alex Waygood 在 Python 基金会博客中提到了上周刚刚举办的Python 语言峰会上关于 Python 语言的重大议题 —— “废除” Python 语言的全局解释器锁(GIL)。

“双刃剑”:CPython —— 解释器和编译器

众所周知,Python 动态语言的灵活性是把“双刃剑”。这意味着可以有不同的运行时,例如 Pyston、Cinder、MicroPython、pypypy 等,它们可能支持整个语言、特定版本或子集。但如果你使用的是 Python,那么你可能正在运行 CPython。

CPython 是用 C 语言编写的标准 Python 解释器,它同时还充当着编译器,因为它的任务是在实际的解释阶段之前以字节码的形式编译 Python 代码。

CPython 有一种称为全局解释器锁 GIL(Global Interpreter Lock)的东西,可以影响线程代码,即一次只能在解释器中运行一个线程。因此,GIL 一直被看做是该语言发展的固有限制。

之前,也一直有提案想要解决这个问题,例如将性能关键部分移到 C 或使用多个解释器。但要满足以上期望,解释器用户的受众可能会扩大。目前有几种替代方案,例如通过专用于 JVM(Java 虚拟机)和 CLR(公共语言运行时)的方案,但以上多数现有的解决方案都有相当大的缺点。

所以基于以上背景,“不带全局解释器锁的 Python” 的支持声逐渐受到关注。

多次尝试被废除:GIL 究竟该如何摆脱掉

直到此次的 Python 语言峰会上,Meta 高级工程总监 Sam Gross 在有关 “nogil”项目的主题中,提出了“废除 GIL ”的相关议题。

据悉,该提议是基于之前在 Python 中废除 GIL 的想法。Gross 最初在使用第三方代码的 Python 项目中遇到了问题,因此开始思考“如果没有 GIL”的话如何使得线程安全的进行。

前面提到过,全局解释器锁 GIL 一次只能在解释器中运行一个线程,所以当你可以保证一次只运行一个线程时,程序状态或许会更容易推理。但如果没有 GIL,引用计数、内存分配、方法解析顺序缓存和垃圾收集线程则会变得不安全。

那么,该如何摆脱 GIL 呢?

据报道,早前 Sam Gross 就专门对这一演变进行了讨论。由于 CPython 中的设计是“线程安全”,但它依赖于 GIL。想要摆脱 GIL,首先,就要对参考计数进行重大更改。

为了知道垃圾收集器是否可以释放内存中的对象,它会统计对该对象的所有引用。目前,引用计数是非原子性的,将所有引用计数操作更改为原子性操作会对性能造成巨大影响。

Sam Gross 在该提案中使用了一种称为“有偏引用计数”(biased reference counting )的技术,用于获取本地和共享引用。本地引用可以利用非原子性操作,拥有线程将本地引用和共享引用结合起来以跟踪所有权。这种方法非常适用于单线程对象,或者只被几个线程少量使用的对象。

在程序的生命周期中存在几个对象,如插入字符串、True、False 和 None,它们可以被标记为“不朽”(immortal),从而将它们的引用计数开销减少到零。通过利用引用计数字段中的最低有效位,对象被标记为“不朽”。经常访问但不能保证“不朽”的对象延迟了引用计数,这意味着唯一需要的引用计数是当引用存储在堆上时,此更改的一个副作用是无法立即回收对象,因为需要扫描堆栈以查找任何剩余的引用。

Sam Gross 用 mimalloc 替换了标准的 pymalloc 内存分配器,mimalloc 是 malloc 的一个替代品,提供了线程安全和性能。这种交换的好处是,这个分配器允许运行时在没有显式列表的情况下查找 GC 跟踪的对象。这是一个显著的性能提升,但这意味着不能只交换另一个与 malloc 兼容的分配器,而期望垃圾收集和收集具有相同的线程安全性。

Python 尚未决定是否删除 GIL

关于为何要删除 GIL 的问题,Python 基金会博客中解释称,“为了让 Python 在没有 GIL 的情况下有效地工作,必须向大多数代码中添加新锁,以确保其保持线程安全,但向现有代码中添加新锁可能非常困难,因为在某些领域可能会出现大幅放缓。”

此次,Sam Gross “删除 GIL”的新提议似乎已经受到了 Python 核心开发团队其他成员的“热情”欢迎。现在,要解决的主要问题是如何在 CPython 上实施如此巨大的变革。

据悉,CPython 的下一个版本(或为 CPython 3.11)预计将于 2022 年 10 月发布,不知道届时会不会有大更新,但报道称开发人员们尤其希望通过此更新获得更高的性能和对在 web 浏览器上下文中运行的支持的集成。

过去的一段时间里,由于 GIL 阻碍了语言的进发,开发者曾多次尝试在标准实现 CPython 中废除这种技术。此次,“删除 GIL”的新提议终于来了,尽管 Python 官方尚未就实施作出最终决定,但一切依旧值得期待。


MissD
955 声望40 粉丝