Python几种并发实现方案的性能比较(Elias)

早期(约2007-2008,Python 2.4 时代)的一篇经典中文实测文章,作者 Elias。针对 Stackless Python、thread 模块、threading+Queue 模块、processing(多进程)+Queue 模块四种并发方案,用与《Erlang vs. Stackless Python: a first benchmark》相同的环形消息实验做性能对比。原文为博客打印 PDF(7页),数值结果表格以图片嵌入无法提取(标注:待确认具体耗时数字),文字结论完整。

实验设计

  • 环形传递问题:n 个节点组成环,m 个消息逐个从 1 号节点发出,1..n-1 号收到后转发下一号,n 号收到即终止;以完成全部处理的总时间评判性能
  • 参数:n=300、m=10000(可扩至 m=90000);全部用 no_io 版本(print 开销大,会污染测试)
  • 平台:Macbook Pro 3,1 + Vmware Fusion 1.0 虚拟机(Debian etch),单核、796MB 内存;Python 2.4.4 + Stackless 3.1b3 + processing-0.52

核心结论(文字部分完整可读)

  1. Stackless Python 性能”匪夷所思”地好:比其他三种方案快几十倍;借助其 channel 机制实现也最简单。文章推测这解释了沈仙人基于 Stackless Python 的 Eurasia3 为何能达到 C 语言效果的并发性能
  2. thread 与 threading 性能差不多(threading 只是 thread 的封装),但 threading+Queue 测试结果不稳定(同代码多轮波动大,原因文中未解);工程体验上 threading+Queue 比裸 thread 轻松且少出错
  3. processing 多进程比 thread 慢约一倍,且这是特意给虚拟机调大内存避免 swap 后的结果(其他方案仅占少量内存);多开 CPU 核心时 processing 可能占优
  4. 多核利用限制:thread 模块不能有效利用多 CPU(GIL);实测 Stackless Python 开双核与单核性能相同,同样不能利用多核
  5. 给出的工程建议(当时Python社区共识):按 CPU 数启动少量进程,进程内部再开线程做业务,processing + 其自带 Queue 编程体验不错。这正是后来 multiprocessing 的标准用法雏形

历史价值与今天的映射

  • 2007 年的结论框架至今仍然成立:GIL 限制线程多核扩展、多进程绕开 GIL 但切换贵、微线程(现在叫协程 asyncio/greenlet)在单线程事件循环下切换成本极低
  • Stackless Python 的”快几十倍”本质是 callable-architectures 微线程 + channel,类比今天的 asyncio/greenlet vs OS 线程
  • Eurasia3 是 Web.py 生态沈崴的作品(Stackless 系 Web 框架),此文是其性能背书的一手材料
  • 具体毫秒级数字在原文中以图片呈现,本地提取不可得,待确认(如需可 OCR 第 4-5 页)

关联