文章通过深入分析 Python 的性能和生态系统,揭示了 Python 如何成为一个强大的编程语言,不仅仅是因为它的“胶水”特性,还因为它在社区中的隐式 JIT 生态系统。
最近,我编写了更多 Rust,这让我对 Python 有了新的认识。Rust 对我最初的任务至关重要,但只需进行一些简化,较短的 Python 版本就可以达到几乎一样快的速度。我从一条冷路跌跌撞撞地走向了一条热路……
我仔细观察,我开始在 Python 的生态系统中随处可见这些热门路径 - 连接优化节点的陈旧路径,由在我之前无数的开发人员随着时间的推移而铺设。
我非常好奇其他人对此有何感受。我一生中一半的时间(近二十年)都在使用 Python,而过去几年则认真使用 Rust。我深爱这两种语言,但现在钟摆又摆回了 Python,这并不是因为我不会使用 Rust,而是因为我觉得我现在对何时以及如何使用 Rust 有了清晰的认识。
你可以:
- 在睡梦中写作
- 根据需要import any_magic(包括全局pip安装)
- 想象一下机器时代初期用 MMIX 汇编编写的弗兰肯斯坦式 FortRust++ 库
- 逐行执行你的代码,直到它(可预见地)中断,让你在解释器中找到问题
事实是这样的:这对于早期发展来说实际上是一个非常好的流程!
这种结合是最为特别的,它体现了 Python 生态系统如何演变以及是什么引导了这种演变的更广阔图景。
当你编写 Python 代码时,你不仅仅是在编写粘合剂,你还是 Python 隐式即时编译生态系统的探索者。
每当新发现的 Python 代码路径变得足够热时,生态系统就会做出响应,从最简单的金属中锻造出一个新组件,然后将其粘合到位。
这种粘合剂并不是静态的。它就像欲望路径一样,根据整个生态系统的使用模式不断演变。
Python 的作用不仅仅是连接组件——它还发现哪些组件需要存在。
Python 性能悖论
Python 很慢。但也许,只是也许,我们可能希望它这样?
当 Python 代码路径变得足够慢时,就会发生一些违反直觉的事情:生态系统不会优化 Python,而是会粘合其他东西。
Python 运行起来很慢,但实验起来却很快。你扮演侦察兵的角色,寻找值得铺设的道路。这些道路更看重表现力、易用性和简单性,而不是性能。你不会赢得性能之战,所以你甚至不会尝试与之抗争。这条路使用得越多,支持它的基础设施就越多。
这是一种新兴的优化策略,其效果比任何规划都更好。
Python 本身就是反对过早优化的。它只是让程序运行起来,然后才决定让它运行得更快(如果这很重要的话)。
Python API 趋向于帕累托最优,通常覆盖 80% 的用例,同时公开 20% 的底层组件功能。我们不会在 Fast™ 语言中重新发明轮子,而是在需要的地方粘贴最佳优化解决方案。
如果我们需要比 Python 的胶水功能更进一步,我们知道我们已经降低了底层组件的风险,并且可以根据需要降低一层抽象。只要 Python API 简单易用,那么 Python 是否用 FortRust++ 编写并不重要。
Python 继续向前发展,针对最终用户功能(易用性、组合性、简单性等)进行优化,而不是针对底层魔法。Python 不会嫉妒其他语言试图窃取来之不易的库。
隐式 JIT 生态系统
在深入探讨之前,让我们先来解释一下“隐式 JIT 生态系统”的含义。
在传统的即时 (JIT) 编译中,程序会在运行时优化其热路径(频繁执行的代码段)。这意味着我们不会花费大量时间优化不重要的代码路径(过早优化),甚至可以根据代码的实际使用方式(而不是我们假设的代码使用方式)找到更好的优化。
Python 生态系统做了一些非常相似的事情,但是是在社区规模上。
Python 的生态系统不是在单个程序的运行时进行优化,而是在整个社区的集体使用模式中进行优化。当 Python 开发人员在某些路径上持续遇到性能瓶颈时,生态系统就会做出反应。
虽然这个优化过程的一部分仅仅是由使用情况驱动的(即在最大、最活跃的生态系统中“追踪”最多的路径),但仅凭这一点并不能解释 Python 的全部成功。
Python 的一些特性增强了这种动态,比如可读性、宽容性,甚至它自己的性能限制(“慢速 Python”),所有这些特性协同作用,创建了一个以可访问、可组合和(最终)高效的方式发现和优化这些路径的环境。
隐式 JIT 生态系统并非 Python 所独有,但 Python 的特性放大并塑造了这种演变的速度和广度。
即使隐式 JIT 生态系统对于任何粘合语言来说都是完全通用的,它也是一种值得考虑的动态语言。
隐式 JIT 生态系统显式化
尽管 Python 可能是最成功的隐式 JIT 生态系统,但它并不是唯一的。我们已经看到这种模式反复出现:从“缓慢”但富有表现力的语言开始,通过实际使用发现热门路径,然后根据需要优化这些特定路径。
随着初创公司成长为科技巨头,他们的工程团队在明确的热门路径上苦苦挣扎:
- Python 有 Instagram(Facebook)和 YouTube(Google)
- Ruby / Ruby on Rails 有 GitHub 和 Shopify
- PHP 诞生了 Facebook,催生了 HHVM 和 Hack
- 最近,Figma 使用 Rust 增强了 JavaScript
Python 是速度最快的慢速语言
Python 中的机器学习和数据科学世界或许是这种隐式 JIT 演进的最明显例子。 Python 代码变得缓慢而重要,是生态系统努力纠正的结构性缺陷。
Python 对数值处理的需求变成了 numpy、pandas、scikit-learn 和其他数百种基础工具。 用 C 和 Cython 编写的代码足以点燃火焰,但我们仍然看到了更多的进步--比如 Polars 正在探索 Rust 可能会将 pandas 代码库带入何处。
ML 框架的演变将这种模式展现得淋漓尽致。
PyTorch 之所以能从 Lua 的 Torch 中脱颖而出,并不是因为 Python 的速度更快,而是因为 Python 的生态系统已经非常完善,而且易用性进一步推动了 Python 的采用。 库必须以 Python 形式出现,否则就有可能被淘汰。
不知何故,我们现在有了 Python,一种“慢速”语言,掌控着世界上大部分的 FLOPS。
胶水语言也是LLM语言
Python 经过优化,变得简洁、宽容、渐进且(相对)简单,非常适合人类使用 - 这与 LLM 的需求完全相同。
对于大多数任务,如果可以的话,您可能不需要超过三行(import、设置、执行)的内容。Python 最适合于此:
- 无需任何开销,
- 一个完整的可互操作组件生态系统,
- 以及一组对于任性的程序员来说极其简单的 API。
隐式 JIT 生态系统获得真正的 JIT
在担任隐式 JIT 生态系统的催化剂数十年后,Python终于在 3.13 中尝试了自己的 JIT。Python中新JIT功能介绍
这是一次合适的演变。我们曾经诅咒的缓慢很可能是生态系统构建热路径的必要催化剂,而 Python 本身永远无法做到这一点。
Python 的性能限制不仅创造了一个优化组件的生态系统,还让我们能够准确地看到哪些路径需要优化,不多也不少。有时,最好的前进之路就是快与慢并存。
摘要:
- 作者通过与 Rust 语言的比较,发现 Python 在某些情况下可以接近 Rust 的性能,尤其是在“热路径”(频繁执行的代码段)上。
- Python 的生态系统中存在许多优化节点,这些节点由社区中的开发者共同优化和维护。
- Python 运行速度慢,但实验速度快。开发者作为探路者,找到值得优化的路径。
- Python 的 API 趋势是帕累托最优,覆盖了大部分用例,同时暴露了底层组件的一小部分能力。
- Python 被优化为简洁、宽容、增量和相对简单,这与 LLMs 的需求完全相同。
网友:
1、它不是一个JIT,而是功能模块的集合。
这在很大程度上取决于你在做什么。
- 如果你需要低级性能,而这些性能可以通过逐个操作映射到相当接近机器操作的东西上,那么像 C++ 或 Rust 这样的语言将比 Python 和其他高级语言高出大约 40 到 50 倍。
- 如果你在高抽象层次上大批量地处理事情,而其中的基本操作与机器操作相差甚远,那么像 Python(或者对于这里的老年人来说甚至是 Perl)这样的语言通常可以接近与低级语言的“较量”,因为功能的“单元”无论如何都是在底层 实现的。
2、python 找到了一个奇怪的正反馈市场,它非常受欢迎,人们有动力为它运行缓慢的任务编写本机模块,这反过来又使它更受欢迎,等等。并且这种情况在某些领域比其他领域更常见(特别是机器学习和数据科学)。Python 的一些特性明确地放大了这一点,比如可读性、宽容性,甚至它自己的性能限制(“慢速 Python”),所有这些特性协同作用,创建了一个以可访问和可组合的方式发现和优化这些路径的环境。
即使这对所有粘合语言来说都是完全通用的,而 Python 只是其中的赢家通吃。