直接回答:3.11 的提速来自 Faster CPython 项目的一组组合拳,核心是 PEP 659 的"特化自适应解释器"(specializing adaptive interpreter):字节码执行若干次后,把通用指令原地替换为针对具体类型的特化版本,并用内联缓存记住操作数类型;一旦类型变化就通过 guard 检查回退(deopt)为通用指令。官方基准套件均值提升约 25%,部分场景 10–60%。
展开解析:具体机制有四层。一是指令特化:比如 BINARY_OP 热起来后变成 BINARY_OP_ADD_INT,省去动态分派和类型检查;属性访问 LOAD_ATTR 特化为按缓存的类型版本号直接读实例 dict 的槽位,跳过描述符协议的完整查找——每条特化指令都带 guard,类型变了即回退并重新自适应。二是零开销异常:try 块不再在运行时建立处理记录,改为编译期生成异常表,异常发生时查表定位 handler,不抛异常时 try 完全零成本。三是更小的栈帧:帧对象从堆分配改为按需惰性创建,字段精简,创建成本大降。四是帧内联:Python 函数调 Python 函数不再递归进入 C 层的求值循环,直接在当前 C 帧里切换数据帧,顺带消除了深层递归爆 C 栈的问题。
实践要点:收益集中在纯 Python 的 CPU 密集代码;NumPy 这类时间花在 C 扩展里的负载几乎无感。3.12 继续扩展特化范围并引入 PEP 669 低开销监控,3.13 又叠加实验性的 copy-and-patch JIT 和 free-threading。升级前要用自己的负载跑压测验证,而不是只看官方均值。
追问方向:去特化的触发条件和代价是什么?PEP 669 的低开销监控如何利用特化指令实现?
(约 560 字)