📰 来源:Towards Data Science | 📅 翻译日期:2026年6月20日
🔗 原文:查看原文
🤖 翻译:DeepSeek AI · 仅供参考
引言
Python 3.14 的发布标志着全球最流行编程语言进化中的一个重要时刻。尽管 Python 长期以来以其可读性和庞大的生态系统而闻名,但其执行速度一直是“房间里的大象”。
随着 3.14 版本的到来,CPython 核心开发团队一次性交付了两个近期最受期待的功能。
GIL 的终结
我之前已经写过相关内容。真正的并发现已可选地存在于 Python 中。如果你想要更多关于无 GIL Python 的细节,我将在文末附上相关文章的链接。
即时编译(JIT)
这一实验性功能现在直接捆绑在官方安装程序中,也是我们本文的重点。它是 Python 核心团队及其他人员多年架构准备的成果,旨在使 Python “默认更快”,同时不破坏从数据科学到 Web 后端等领域的 C 扩展生态系统。
在本文中,我们将深入解析新的 JIT,探讨其与以往优化工作的区别,并介绍一些基准测试方法,帮助你判断是否值得在工作负载中试用 JIT。
什么是 Python 的新即时编译(JIT)?
要理解 3.14 的 JIT,我们需要了解 Python 传统的运行方式。标准 Python(CPython)是一种解释型语言。当你运行脚本时,代码会被编译成字节码,这些字节码是 CPython 虚拟机执行的一套指令。
JIT 改变了这一流程。JIT 不是简单地逐行解释字节码,而是监测代码中最频繁执行的部分(热点路径)。当某个函数或循环被判定为“热点”时,JIT 会将字节码翻译成原生机器码(CPU 能理解的指令)。然后,下次调用该代码时,无需再解释,直接运行机器码。这可以大大节省时间,稍后我们将看到。
JIT 如何融入 CPython
Python 3.14 的 JIT 并非完全重写。它被设计为可选组件,与现有的解释器协同工作。它采用“复制并修补”技术,使其轻量且可移植到不同的 CPU 架构,无需像 LLVM 那样庞大复杂的编译器后端。
Python 3.14 中的变化
Python 3.13 有一个基础的、实验性的 JIT,但默认禁用。如果您想测试,必须克隆 CPython 源码树,并使用特定实验标志(如 --enable-experimental-jit)编译。
在 Python 3.14 中,一切都变了。它在官方 .msi(Windows)和 .pkg(macOS)安装程序中提供了 JIT。这意味着您不再需要 C 编译器即可体验 JIT 的优势。虽然仍处于“实验性”阶段,但包含在官方二进制文件中表明核心团队认为 JIT 已足够稳定,可供社区广泛测试。
获取 Python 3.14
前往 https://www.python.org/downloads/,您会看到 3.14 的下载选项。点击并按照说明操作。
或者,如果您安装了 UV 工具,可以输入以下命令:
PS C:\ > uv python install 3.14启用 JIT
默认情况下,JIT 是禁用的。这是一种安全措施;因为它是实验性的,Python 指导委员会希望确保用户不会在没有明确选择的情况下遇到稳定性或内存使用方面的意外回归。
要激活 JIT,您需要使用一个环境变量。这会告知 CPython 运行时在启动时初始化 JIT 引擎。
在 Windows(PowerShell)上:
$env:PYTHON_JIT=1 python my_script.py在 macOS/Linux(Bash/Zsh)上:
PYTHON_JIT=1 python my_script.py
一旦启用,CPython 不会立即 JIT 编译所有内容。它采用分层系统:
- Tier 0:标准解释。
- Tier 1:专用字节码(3.11 引入)。
- Tier 2(JIT):为最常用路径生成机器码。
衡量 JIT 的影响
测试 JIT 时,不能简单地在函数周围使用 time.time()。JIT 需要预热期。循环的前几次迭代可能比正常情况慢,因为 JIT 在分析代码,但后续迭代可能快得多。
基准测试套件
以下是一套全面的测试套件,旨在从繁重数学到复杂对象操作等不同方面测试 JIT。
文件:workloads.py
此文件包含三个不同的 CPU 密集型任务:
- Mandelbrot 函数:在像素网格上迭代 Mandelbrot 公式,返回每个像素迭代次数的校验和。
- Dijkstra 函数:构建一个确定性随机加权图,从节点 0 运行 Dijkstra 算法,返回最终确定/访问的节点数。
- Levenshtein 函数:生成 N 对确定性随机字符串,返回它们的 Levenshtein 距离之和。
from __future__ import annotations
import random
import heapq
# Workload 1: Mandelbrot (CPU + math loops)
def mandelbrot(width: int = 1000, height: int = 1000, iters: int = 500) -> int:
checksum = 0
for y in range(height):
cy = (y / height) * 2.4 - 1.2
for x in range(width):
cx = (x / width) * 3.2 - 2.2
zx, zy, count = 0.0, 0.0, 0
while zx * zx + zy * zy <= 4.0 and count < iters:
zx, zy = zx * zx - zy * zy + cx, 2.0 * zx * zy + cy
count += 1
checksum += count
return checksum
# Workload 2: Dijkstra (heap + list + logic)
def dijkstra(n: int = 10000, edges_per_node: int = 50, seed: int = 123) -> int:
rng = random.Random(seed)
graph = [[] for _ in range(n)]
for u in range(n):
for _ in range(edges_per_node):
v = rng.randrange(n)
if v != u:
graph[u].append((v, rng.randrange(1, 30)))
评论已关闭