zoo-bench · 2026-10-11 · AMD EPYC 7763 64-Core Processor

zoo-framework 0.11.2-beta
性能评测

与 apscheduler、asyncio_pool、bare_thread、process_pool、thread_pool 共 5 个对照方案的同口径对比;全部数值由 zoo-bench 在本机重新测量、逐档公开,包括本框架输掉的档位。

原始数据:results/zoo-framework-dev/20261011T094251Z.json

zoo-bench 报告

运行环境

项值
CPU 型号AMD EPYC 7763 64-Core Processor
逻辑核数4
平台Linux-x86_64
操作系统Linux 6.17.0-1022-azure(#22-Ubuntu SMP Mon Jul 27 17:24:03 UTC 2026)
PythonCPython 3.13.16
解释器/opt/hostedtoolcache/Python/3.13.16/x64/bin/python
GILdefault
被测框架(发行元数据)0.11.2-beta
被测框架(模块 __version__)0.11.2-beta(仅附注,不作版本判据)
被测框架的驱动面世代当前代驱动面(调度内核 core + 调度模型 model,完成信号取自结果响应器)
安装来源git 的 dev
提交44dcbca5f392
harnesszoo-bench 0.0.1 @ 9a42be24ac43f75e2e5d7b16434f91ba3d0717b6

数据:运行环境

运行环境

运行环境(续)

项值
复现命令zoo-bench run --framework zoo-framework @ git+https://github.com/YearsAlso/zoo-framework.git@dev

以 dist_version(发行元数据)为版本真源;module_version 仅作附注

数据:运行环境

zoo-bench 报告

负载

  • 构成:单位工作 = JSON 序列化 + 反序列化 + 字符串拼接,重复若干次以达到目标耗时;档位由 matrix.yaml 的 body_tiers_us 声明
  • 负载是替身,不是真实 trace:形状接近“取一帧数据 -> 序列化 -> 解析 -> 字符串处理”这类业务动作,但仓库内没有真实样本,结论的适用性以此为前提

数据:负载

zoo-bench 报告

测量口径

  • 执行体耗时在同一次运行内埋点:由执行体在自身内部测量并回传,框架开销 =端到端 - 它。不做跨运行减法——两次运行的状态不同(缓存、频率、调度噪声),相减引入的是系统性偏差。
  • 预热不入统计:每个单元先跑 3 轮预热并丢弃,只统计随后的 30 轮正式采样;采样数等于「正式轮数 x 并发度」。
  • 绝对耗时不可跨运行比较:它只用于看量级;跨版本/跨机器要看的是同一次运行内的相对量(开销占比、相对各对照方案的倍数),它们对整体快慢不敏感。

数据:测量口径

zoo-bench 报告

结论摘要

  • 被测框架 zoo 的执行体时长达到约 2700 微秒 及以上时,其框架开销占端到端的比例降到 15% 以下;短于此档位,选用它的主要代价就是框架开销本身。
  • 并发度 1、执行体 40 微秒 下,被测框架比 process_pool 快 2.31x(该并发度所测档位中最快的一档)。
  • 并发度 1 下,执行体时长超过约 40 微秒 后,apscheduler 不再快于被测框架。
  • 并发度 4 下,执行体时长超过约 40 微秒 后,apscheduler 不再快于被测框架。
  • 并发度 16 下,执行体时长超过约 40 微秒 后,apscheduler 不再快于被测框架。
  • 并发度 64 下,执行体时长超过约 40 微秒 后,apscheduler 不再快于被测框架。
  • 并发度 1 下,所测档位内 asyncio_pool 始终快于被测框架——这类档位正是本报告的公开不利数据。

数据:结论摘要

结论摘要

结论摘要(续)

  • 并发度 4 下,所测档位内 asyncio_pool 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 16 下,所测档位内 asyncio_pool 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 64 下,所测档位内 asyncio_pool 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 1 下,所测档位内 bare_thread 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 4 下,所测档位内 bare_thread 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 16 下,所测档位内 bare_thread 始终快于被测框架——这类档位正是本报告的公开不利数据。
  • 并发度 64 下,所测档位内 bare_thread 始终快于被测框架——这类档位正是本报告的公开不利数据。

数据:结论摘要

结论摘要

本章其余明细在全文里

幻灯片为了「一页一个结论」只放了本章的前 2 页;余下 6 页的逐单元数值、分位数与原始样本都在全文的同一章节里,逐字可核。

全文:同目录 report.md 的「结论摘要」章节

结论摘要 · 框架自身开销占比

1.63%

执行体 10000 微秒 时,zoo 的框架自身开销占比。
该档位有 2 个方案更低:bare_thread、thread_pool。
同档对比:apscheduler 3.50%、asyncio_pool 1.71%、bare_thread 1.36%、process_pool 3.65%、thread_pool 0.60%

数据:zoo-bench「框架自身开销占比」· 并发度 1 · 执行体 10000 微秒 档

维度:延迟分位数与抖动

延迟分位数与抖动:并发度 1

并发度 1 · 端到端 / 并发度

执行体 40 微秒
zoo
151.05 微秒
apscheduler
287.86 微秒
asyncio_pool
142.30 微秒
bare_thread
145.22 微秒
process_pool
349.41 微秒
thread_pool
75.73 微秒
执行体 300 微秒
zoo
410.28 微秒
apscheduler
553.65 微秒
asyncio_pool
385.12 微秒
bare_thread
388.13 微秒
process_pool
590.88 微秒
thread_pool
313.96 微秒
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「延迟分位数与抖动」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

维度:延迟分位数与抖动

延迟分位数与抖动:并发度 1(续)

并发度 1 · 端到端 / 并发度

执行体 2700 微秒
zoo
2.753 毫秒
apscheduler
2.987 毫秒
asyncio_pool
2.699 毫秒
bare_thread
2.634 毫秒
process_pool
2.988 毫秒
thread_pool
2.667 毫秒
执行体 10000 微秒
zoo
9.871 毫秒
apscheduler
9.941 毫秒
asyncio_pool
9.474 毫秒
bare_thread
9.553 毫秒
process_pool
9.773 毫秒
thread_pool
9.525 毫秒
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「延迟分位数与抖动」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

zoo-bench 报告

维度:延迟分位数与抖动

端到端 / 并发度;分位数与相对离散度同表给出,只给中位数的度量不合格

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
140151.05 微秒287.86 微秒142.30 微秒145.22 微秒349.41 微秒75.73 微秒
1300410.28 微秒553.65 微秒385.12 微秒388.13 微秒590.88 微秒313.96 微秒
127002.753 毫秒2.987 毫秒2.699 毫秒2.634 毫秒2.988 毫秒2.667 毫秒
1100009.871 毫秒9.941 毫秒9.474 毫秒9.553 毫秒9.773 毫秒9.525 毫秒
440174.59 微秒252.70 微秒162.47 微秒158.14 微秒167.32 微秒97.54 微秒
4300449.42 微秒521.58 微秒422.43 微秒412.54 微秒306.62 微秒346.42 微秒
427002.911 毫秒2.912 毫秒2.754 毫秒2.683 毫秒1.390 毫秒2.689 毫秒
4100009.949 毫秒9.993 毫秒9.670 毫秒9.713 毫秒4.653 毫秒9.529 毫秒
1640177.55 微秒229.36 微秒133.81 微秒171.28 微秒156.46 微秒90.20 微秒
16300466.12 微秒505.80 微秒396.45 微秒423.99 微秒275.04 微秒345.34 微秒
1627002.908 毫秒2.947 毫秒2.770 毫秒2.705 毫秒1.381 毫秒2.740 毫秒

数据:维度:延迟分位数与抖动

维度:延迟分位数与抖动

维度:延迟分位数与抖动(续)

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
161000010.146 毫秒10.216 毫秒9.917 毫秒9.716 毫秒4.712 毫秒9.785 毫秒
6440205.09 微秒221.11 微秒121.88 微秒170.85 微秒204.14 微秒91.39 微秒
64300462.64 微秒509.59 微秒381.72 微秒425.01 微秒307.25 微秒352.74 微秒
6427002.884 毫秒2.905 毫秒2.779 毫秒2.746 毫秒1.379 毫秒2.647 毫秒
641000010.447 毫秒10.197 毫秒9.811 毫秒9.532 毫秒4.713 毫秒10.238 毫秒

逐单元数值(分位数、离散度、各轮原始样本)见文末「附录:全部数值」。

数据:维度:延迟分位数与抖动

维度:框架自身开销占比

框架自身开销占比:并发度 1

并发度 1 · 框架自身开销

执行体 40 微秒
zoo
67.93%
apscheduler
82.43%
asyncio_pool
67.30%
bare_thread
64.62%
process_pool
84.22%
thread_pool
41.18%
执行体 300 微秒
zoo
28.03%
apscheduler
45.95%
asyncio_pool
27.77%
bare_thread
26.48%
process_pool
49.33%
thread_pool
11.25%
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「框架自身开销占比」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

维度:框架自身开销占比

框架自身开销占比:并发度 1(续)

并发度 1 · 框架自身开销

执行体 2700 微秒
zoo
5.00%
apscheduler
9.52%
asyncio_pool
4.39%
bare_thread
4.23%
process_pool
11.32%
thread_pool
1.80%
执行体 10000 微秒
zoo
1.63%
apscheduler
3.50%
asyncio_pool
1.71%
bare_thread
1.36%
process_pool
3.65%
thread_pool
0.60%
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「框架自身开销占比」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

zoo-bench 报告

维度:框架自身开销占比

开销 = 端到端/并发度 - 同一次运行内实测的执行体耗时(不做跨运行减法)。带 — 的格:该并发度超出这台机器的并行能力,执行体自报耗时含超订的调度等待,与该行的每任务端到端不可比,故不给开销数字(端到端与吞吐见各自的维度)

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
14067.93%82.43%67.30%64.62%84.22%41.18%
130028.03%45.95%27.77%26.48%49.33%11.25%
127005.00%9.52%4.39%4.23%11.32%1.80%
1100001.63%3.50%1.71%1.36%3.65%0.60%
44072.39%77.98%67.61%68.53%43.29%48.41%
430033.16%40.01%26.84%27.97%—15.15%
427006.07%9.25%5.48%4.89%—3.51%
410000——————
1640——————
16300——————
162700——————

数据:维度:框架自身开销占比

维度:框架自身开销占比

维度:框架自身开销占比(续)

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
1610000——————
6440——————
64300——————
642700——————
6410000——————

逐单元数值(分位数、离散度、各轮原始样本)见文末「附录:全部数值」。

数据:维度:框架自身开销占比

维度:吞吐与并发伸缩

吞吐与并发伸缩:并发度 1

并发度 1 · 吞吐

执行体 40 微秒
zoo
6,620 任务/秒
apscheduler
3,474 任务/秒
asyncio_pool
7,028 任务/秒
bare_thread
6,886 任务/秒
process_pool
2,862 任务/秒
thread_pool
13,204 任务/秒
执行体 300 微秒
zoo
2,437 任务/秒
apscheduler
1,806 任务/秒
asyncio_pool
2,597 任务/秒
bare_thread
2,576 任务/秒
process_pool
1,692 任务/秒
thread_pool
3,185 任务/秒
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「吞吐与并发伸缩」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

维度:吞吐与并发伸缩

吞吐与并发伸缩:并发度 1(续)

并发度 1 · 吞吐

执行体 2700 微秒
zoo
363 任务/秒
apscheduler
335 任务/秒
asyncio_pool
370 任务/秒
bare_thread
380 任务/秒
process_pool
335 任务/秒
thread_pool
375 任务/秒
执行体 10000 微秒
zoo
101 任务/秒
apscheduler
101 任务/秒
asyncio_pool
106 任务/秒
bare_thread
105 任务/秒
process_pool
102 任务/秒
thread_pool
105 任务/秒
被测框架对照方案条形 = 相对被测框架的倍数,1.0 为持平,越长越差

数据:zoo-bench「吞吐与并发伸缩」· 并发度 1 · 逐单元数值与分位数见 report.md 的同一章节

zoo-bench 报告

维度:吞吐与并发伸缩

吞吐 = 并发度 / 端到端中位数;随并发度是否继续上升即为伸缩性

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
1406620.43473.97027.66886.02862.013204.5
13002437.41806.22596.62576.41692.43185.1
12700363.2334.8370.4379.6334.6375.0
110000101.3100.6105.5104.7102.3105.0
44022910.915828.824620.625293.923906.041009.0
43008900.37669.09468.99696.113045.311546.7
427001374.21373.41452.51491.02878.51487.4
410000402.1400.3413.6411.8859.6419.8
164090116.969759.2119571.293414.7102262.4177375.4
1630034326.231632.840357.737737.058172.446331.7
1627005501.65429.25775.35915.811588.25838.4

数据:维度:吞吐与并发伸缩

维度:吞吐与并发伸缩

维度:吞吐与并发伸缩(续)

并发度执行体档位(微秒)zooapschedulerasyncio_poolbare_threadprocess_poolthread_pool
16100001577.01566.21613.41646.83395.61635.2
6440312054.2289446.9525124.2374606.5313503.0700311.8
64300138336.3125590.4167662.6150584.2208301.1181435.9
64270022191.322031.023032.223310.346410.524173.8
64100006126.46276.16523.56714.213578.06251.0

逐单元数值(分位数、离散度、各轮原始样本)见文末「附录:全部数值」。

数据:维度:吞吐与并发伸缩

zoo-bench 报告

维度:开销归因

口径:把每任务端到端拆成提交侧 / 手交 / 执行体 / 回程四段,并在同一档位与并发度下与各对照方案逐段对照,回答「超出对照的部分落在哪一段」。它是诊断而非主证据:抽样一小批档位,且不与对照方案比总开销。手交为负不是错误:那表示提交调用还没返回、执行体就已经开跑——把建线程一类工作算进提交侧的方案就会这样(实测 bare_thread 手交 -343 微秒)。回程含完成信号的等待(排空返回前的最后一段),它与主测量是同一口径

状态:ok

本维度是诊断不是主证据:抽样的档位与并发度固定为一小批,不覆盖矩阵里的全部单元。并发度上界取机器的并行能力——超过它时量到的是争用;

抽样档位(微秒):40、10000;并发度:[1, 4];该机器并行能力:4

方案并发度档位(微秒)提交侧手交执行体回程状态
apscheduler140108.63 微秒91.69 微秒50.72 微秒40.59 微秒ok
apscheduler440109.96 微秒509.17 微秒53.33 微秒229.15 微秒ok
apscheduler110000165.03 微秒115.08 微秒9.620 毫秒54.23 微秒ok

数据:维度:开销归因

维度:开销归因

维度:开销归因(续)

方案并发度档位(微秒)提交侧手交执行体回程状态
apscheduler410000124.65 微秒10.534 毫秒14.747 毫秒9.563 毫秒ok
asyncio_pool14017.86 微秒27.78 微秒46.74 微秒61.41 微秒ok
asyncio_pool44019.51 微秒277.63 微秒56.04 微秒298.30 微秒ok
asyncio_pool11000024.40 微秒38.13 微秒9.282 毫秒88.21 微秒ok
asyncio_pool41000023.24 微秒12.312 毫秒14.438 毫秒9.637 毫秒ok
bare_thread140142.97 微秒-77.02 微秒53.08 微秒31.00 微秒ok
bare_thread440156.85 微秒-76.12 微秒51.67 微秒320.79 微秒ok
bare_thread1100005.183 毫秒-5103.28 微秒9.413 毫秒40.28 微秒ok
bare_thread4100005.193 毫秒-5086.31 微秒14.456 毫秒9.546 毫秒ok
process_pool140————not_measurable:执行体的起止时刻读不到——它没有在本进程里运行(跨进程档位无法这样分段)
process_pool440————not_measurable:执行体的起止时刻读不到——它没有在本进程里运行(跨进程档位无法这样分段)
process_pool110000————not_measurable:执行体的起止时刻读不到——它没有在本进程里运行(跨进程档位无法这样分段)
process_pool410000————not_measurable:执行体的起止时刻读不到——它没有在本进程里运行(跨进程档位无法这样分段)

数据:维度:开销归因

维度:开销归因

本章其余明细在全文里

幻灯片为了「一页一个结论」只放了本章的前 2 页;余下 9 页的逐单元数值、分位数与原始样本都在全文的同一章节里,逐字可核。

全文:同目录 report.md 的「维度:开销归因」章节

zoo-bench 报告

维度:调度语义的代价

口径:本维度采用内部开关对照(同一 workload 下语义全关 vs 逐个开启),不与对照方案横向比较——裸写法没有优先级/超时/重试的对应物,故只能回答“本框架的语义值多少钱”,不能回答“比裸写法贵多少”

状态:ok(结论在该次测量装着的「current」代驱动面上得出)

语义项层级探查方式可测证据 / 原因
超时派发层行为探查(按调度轮反复驱动,量在飞表摘除时刻)是已观测到超时摘除:在执行体结束之前离开在飞表(0.0122s)(执行体 0.15s、run_timeout 0.01s);判定动作在 dispatch_core.py:472;生效的是观测与熔断(记录、标记不健康、摘除在飞登记、停止派发),不是终止仍在执行的 worker——CPython 无法安全中断线程
优先级事件层结构探查(检查执行所需的符号是否存在)否未复核:本项的结论是在「previous」代上得出的,把它当成本代的事实等于在报告里断言一个当前代并不具备的接线。重新推导需要单独一次探查设计(每项要有干净的开/关态才谈得上定价)
重试事件层结构探查(检查执行所需的符号是否存在)否未复核:本项的结论是在「previous」代上得出的,把它当成本代的事实等于在报告里断言一个当前代并不具备的接线。重新推导需要单独一次探查设计(每项要有干净的开/关态才谈得上定价)

本结论按被测版本得出,坐标只对该版本成立;往 matrix.yaml 追加版本后须重跑本探查

数据:维度:调度语义的代价

zoo-bench 报告

维度:原生任务线:同一被测对象的三种执行形态

口径:该线独立测量:它不进入主矩阵的透视表与交叉点,其数值也不可与那些表里的对照方案横向比较

该线结论:ok

等价性门禁:通过,15 条判据输入与 Python 参照逐字节比对(输入上限 256 字节)

所测任务 modbus_rtu.parse_response——Modbus RTU 响应帧解析:输入是一条裸 RTU ADU 响应帧(不含任何传输层封装),其长度即该档位的帧字节

规模档位 R1、R8、R125(帧字节 7、21、255);并发度 1、4、16、64;每格预热 100 轮 + 采样 100 轮,每个并发度一个子进程(共 4 个)

规模分界(只在判定并发度 1 上判读):原生形态更快的档位:R8、R125;更慢的档位:R1;分辨不出的档位:无。分界点:帧不超过 7 字节时原生形态不快,达到或超过 21 字节时更快

每个数值是每任务端到端(正式采样轮的中位数)——与主矩阵延迟维度同一口径

数据:维度:原生任务线:同一被测对象的三种执行形态

维度:原生任务线:同一被测对象的三种执行形态

维度:原生任务线:同一被测对象的三种执行形态(续)

档位(微秒)帧字节并发度纯解释原生扩展在线路由原生扩展 / 纯解释在线路由 / 纯解释更快的一方
R171189.78 微秒192.82 微秒239.17 微秒1.02x1.26x纯解释
R174260.82 微秒268.30 微秒277.48 微秒1.03x1.06x纯解释
R1716255.22 微秒264.64 微秒275.81 微秒1.04x1.08x纯解释
R1764257.22 微秒266.34 微秒282.83 微秒1.04x1.10x未决
R8211216.56 微秒205.28 微秒258.46 微秒0.95x1.19x原生扩展
R8214291.65 微秒271.99 微秒304.52 微秒0.93x1.04x未决
R82116284.36 微秒278.61 微秒303.14 微秒0.98x1.07x未决
R82164282.44 微秒281.62 微秒307.27 微秒1.00x1.09x未决
R1252551643.52 微秒410.37 微秒470.20 微秒0.64x0.73x原生扩展
R1252554698.27 微秒495.83 微秒515.80 微秒0.71x0.74x原生扩展
R12525516688.63 微秒498.11 微秒516.04 微秒0.72x0.75x原生扩展
R12525564675.87 微秒497.24 微秒525.11 微秒0.74x0.78x原生扩展

数据:维度:原生任务线:同一被测对象的三种执行形态

维度:原生任务线:同一被测对象的三种执行形态

本章其余明细在全文里

幻灯片为了「一页一个结论」只放了本章的前 2 页;余下 2 页的逐单元数值、分位数与原始样本都在全文的同一章节里,逐字可核。

全文:同目录 report.md 的「维度:原生任务线:同一被测对象的三种执行形态」章节

zoo-bench 报告

被测框架在哪些档位更快

被测框架处于优势的档位(两侧差异大于该档位的带宽)。它与「公开的不利数据」出自同一份同运行内的相对比,只是一个取更快的、一个取更慢的——两者的覆盖面相同,故谁都挑不了档位。本节的缺席不构成不合格:分不出胜负或处处更慢时它就应当是空的

对照方案并发度执行体档位(微秒)差距被测框架中位数
apscheduler140被测框架比 apscheduler 快 1.91x151.05 微秒
process_pool140被测框架比 process_pool 快 2.31x151.05 微秒
apscheduler1300被测框架比 apscheduler 快 1.35x410.28 微秒
process_pool1300被测框架比 process_pool 快 1.44x410.28 微秒
apscheduler12700被测框架比 apscheduler 快 1.08x2.753 毫秒
process_pool12700被测框架比 process_pool 快 1.09x2.753 毫秒
apscheduler440被测框架比 apscheduler 快 1.45x174.59 微秒
apscheduler4300被测框架比 apscheduler 快 1.16x449.42 微秒
apscheduler1640被测框架比 apscheduler 快 1.29x177.55 微秒
apscheduler16300被测框架比 apscheduler 快 1.09x466.12 微秒
apscheduler64300被测框架比 apscheduler 快 1.10x462.64 微秒

数据:被测框架在哪些档位更快

公开的不利数据 · 归类

被测框架在 45 个档位上更慢,来自 4 个对照方案。

asyncio_pool · 10 个档位更快

最差 1.68x(并发 64 · 40 微秒)。全部档位:并发 1 · 10000 微秒、并发 4 · 2700 微秒、并发 4 · 10000 微秒、并发 16 · 40 微秒、并发 16 · 300 微秒、并发 16 · 2700 微秒、并发 64 · 40 微秒、并发 64 · 300 微秒、并发 64 · 2700 微秒、并发 64 · 10000 微秒

bare_thread · 12 个档位更快

最差 1.20x(并发 64 · 40 微秒)。全部档位:并发 1 · 2700 微秒、并发 1 · 10000 微秒、并发 4 · 300 微秒、并发 4 · 2700 微秒、并发 4 · 10000 微秒、并发 16 · 300 微秒、并发 16 · 2700 微秒、并发 16 · 10000 微秒、并发 64 · 40 微秒、并发 64 · 300 微秒、并发 64 · 2700 微秒、并发 64 · 10000 微秒

process_pool · 9 个档位更快

最差 2.22x(并发 64 · 10000 微秒)。全部档位:并发 4 · 300 微秒、并发 4 · 2700 微秒、并发 4 · 10000 微秒、并发 16 · 300 微秒、并发 16 · 2700 微秒、并发 16 · 10000 微秒、并发 64 · 300 微秒、并发 64 · 2700 微秒、并发 64 · 10000 微秒

thread_pool · 14 个档位更快

最差 2.24x(并发 64 · 40 微秒)。全部档位:并发 1 · 40 微秒、并发 1 · 300 微秒、并发 1 · 10000 微秒、并发 4 · 40 微秒、并发 4 · 300 微秒、并发 4 · 2700 微秒、并发 4 · 10000 微秒、并发 16 · 40 微秒、并发 16 · 300 微秒、并发 16 · 2700 微秒、并发 16 · 10000 微秒、并发 64 · 40 微秒、并发 64 · 300 微秒、并发 64 · 2700 微秒

数据:zoo-bench「公开的不利数据」· 逐档明细见其后的页与 report.md

zoo-bench 报告

公开的不利数据

被测框架处于劣势的档位(两侧差异大于该档位的带宽)。这部分缺失的报告不合格——一份只展示自己赢的报告,读者有理由认为它不可信。差异小于带宽的档位不在本节,而在「分不出胜负」那一节:那是判据的结果,不是把它们藏起来

对照方案并发度执行体档位(微秒)差距被测框架中位数
thread_pool140thread_pool 比 zoo 快 1.99x151.05 微秒
thread_pool1300thread_pool 比 zoo 快 1.31x410.28 微秒
bare_thread12700bare_thread 比 zoo 快 1.05x2.753 毫秒
asyncio_pool110000asyncio_pool 比 zoo 快 1.04x9.871 毫秒
bare_thread110000bare_thread 比 zoo 快 1.03x9.871 毫秒
thread_pool110000thread_pool 比 zoo 快 1.04x9.871 毫秒
thread_pool440thread_pool 比 zoo 快 1.79x174.59 微秒
bare_thread4300bare_thread 比 zoo 快 1.09x449.42 微秒
process_pool4300process_pool 比 zoo 快 1.47x449.42 微秒
thread_pool4300thread_pool 比 zoo 快 1.30x449.42 微秒
asyncio_pool42700asyncio_pool 比 zoo 快 1.06x2.911 毫秒

数据:公开的不利数据

公开的不利数据

公开的不利数据(续)

对照方案并发度执行体档位(微秒)差距被测框架中位数
bare_thread42700bare_thread 比 zoo 快 1.09x2.911 毫秒
process_pool42700process_pool 比 zoo 快 2.09x2.911 毫秒
thread_pool42700thread_pool 比 zoo 快 1.08x2.911 毫秒
asyncio_pool410000asyncio_pool 比 zoo 快 1.03x9.949 毫秒
bare_thread410000bare_thread 比 zoo 快 1.02x9.949 毫秒
process_pool410000process_pool 比 zoo 快 2.14x9.949 毫秒
thread_pool410000thread_pool 比 zoo 快 1.04x9.949 毫秒
asyncio_pool1640asyncio_pool 比 zoo 快 1.33x177.55 微秒
thread_pool1640thread_pool 比 zoo 快 1.97x177.55 微秒
asyncio_pool16300asyncio_pool 比 zoo 快 1.18x466.12 微秒
bare_thread16300bare_thread 比 zoo 快 1.10x466.12 微秒
process_pool16300process_pool 比 zoo 快 1.69x466.12 微秒
thread_pool16300thread_pool 比 zoo 快 1.35x466.12 微秒

数据:公开的不利数据

公开的不利数据

公开的不利数据(续)

对照方案并发度执行体档位(微秒)差距被测框架中位数
asyncio_pool162700asyncio_pool 比 zoo 快 1.05x2.908 毫秒
bare_thread162700bare_thread 比 zoo 快 1.08x2.908 毫秒
process_pool162700process_pool 比 zoo 快 2.11x2.908 毫秒
thread_pool162700thread_pool 比 zoo 快 1.06x2.908 毫秒
bare_thread1610000bare_thread 比 zoo 快 1.04x10.146 毫秒
process_pool1610000process_pool 比 zoo 快 2.15x10.146 毫秒
thread_pool1610000thread_pool 比 zoo 快 1.04x10.146 毫秒
asyncio_pool6440asyncio_pool 比 zoo 快 1.68x205.09 微秒
bare_thread6440bare_thread 比 zoo 快 1.20x205.09 微秒
thread_pool6440thread_pool 比 zoo 快 2.24x205.09 微秒
asyncio_pool64300asyncio_pool 比 zoo 快 1.21x462.64 微秒
bare_thread64300bare_thread 比 zoo 快 1.09x462.64 微秒
process_pool64300process_pool 比 zoo 快 1.51x462.64 微秒

数据:公开的不利数据

公开的不利数据

公开的不利数据(续)

对照方案并发度执行体档位(微秒)差距被测框架中位数
thread_pool64300thread_pool 比 zoo 快 1.31x462.64 微秒
asyncio_pool642700asyncio_pool 比 zoo 快 1.04x2.884 毫秒
bare_thread642700bare_thread 比 zoo 快 1.05x2.884 毫秒
process_pool642700process_pool 比 zoo 快 2.09x2.884 毫秒
thread_pool642700thread_pool 比 zoo 快 1.09x2.884 毫秒
asyncio_pool6410000asyncio_pool 比 zoo 快 1.06x10.447 毫秒
bare_thread6410000bare_thread 比 zoo 快 1.10x10.447 毫秒
process_pool6410000process_pool 比 zoo 快 2.22x10.447 毫秒

原生任务线是独立的一条线,不与上表混读:在它的判定并发度 1 上,原生形态更慢的档位:R1;路由形态慢于纯解释形态的档位:R1、R8;两者都在「原生任务线:同一被测对象的三种执行形态」一节内与有利档位对等列出,出自同一轮同一份配对差

数据:公开的不利数据

zoo-bench 报告

分不出胜负的档位

两侧分不出胜负的档位:差异小于该档位的带宽。带宽取自同一次运行内两侧各自的跨轮离散度(每任务中位数的标准差 / 中位数)之和,故它随样本变化,读者可用留档里的逐轮样本自行复核。它同样覆盖全部所测档位、逐项写明原因——本节不是藏东西的地方:把噪声级差异报成「快 1.00x」才是

判据:带宽 = 被测框架侧与对照侧各自的跨轮相对离散度之和;单侧的跨轮相对离散度 = 该单元逐轮的「每任务中位数」的标准差 / 中位数

本期带宽:1.3% 到 50.0%(随各档位的离散度不同而不同)。

对照方案并发度执行体档位(微秒)比值原因
asyncio_pool1400.94x两侧差异 5.8% 小于带宽 19.9%,分不出胜负
bare_thread1400.96x两侧差异 3.9% 小于带宽 19.5%,分不出胜负
asyncio_pool13000.94x两侧差异 6.1% 小于带宽 7.9%,分不出胜负
bare_thread13000.95x两侧差异 5.4% 小于带宽 7.7%,分不出胜负
asyncio_pool127000.98x两侧差异 2.0% 小于带宽 3.2%,分不出胜负
thread_pool127000.97x两侧差异 3.2% 小于带宽 3.4%,分不出胜负

数据:分不出胜负的档位

分不出胜负的档位

分不出胜负的档位(续)

对照方案并发度执行体档位(微秒)比值原因
apscheduler1100001.01x两侧差异 0.7% 小于带宽 1.3%,分不出胜负
process_pool1100000.99x两侧差异 1.0% 小于带宽 2.6%,分不出胜负
asyncio_pool4400.93x两侧差异 6.9% 小于带宽 21.6%,分不出胜负
bare_thread4400.91x两侧差异 9.4% 小于带宽 13.9%,分不出胜负
process_pool4400.96x两侧差异 4.2% 小于带宽 31.7%,分不出胜负
asyncio_pool43000.94x两侧差异 6.0% 小于带宽 7.6%,分不出胜负
apscheduler427001.00x两侧差异 0.1% 小于带宽 2.4%,分不出胜负
apscheduler4100001.00x两侧差异 0.4% 小于带宽 1.7%,分不出胜负
bare_thread16400.96x两侧差异 3.5% 小于带宽 14.8%,分不出胜负
process_pool16400.88x两侧差异 11.9% 小于带宽 27.7%,分不出胜负
apscheduler1627001.01x两侧差异 1.3% 小于带宽 2.4%,分不出胜负
apscheduler16100001.01x两侧差异 0.7% 小于带宽 1.8%,分不出胜负
asyncio_pool16100000.98x两侧差异 2.3% 小于带宽 3.0%,分不出胜负

数据:分不出胜负的档位

分不出胜负的档位

本章其余明细在全文里

幻灯片为了「一页一个结论」只放了本章的前 2 页;余下 1 页的逐单元数值、分位数与原始样本都在全文的同一章节里,逐字可核。

全文:同目录 report.md 的「分不出胜负的档位」章节

zoo-bench 报告

口径局限与偏差来源

  • 被测层级:调度派发层:直接驱动 BaseWaiter.execute_service()(线程池模式),不走 Master 的完整运行循环——后者的服务循环每秒一次,会把延迟量级从微秒抬到秒。每提交一个任务走一次调度轮,故该轮的全部簿记都计在这一个任务头上;Master 的用法是每轮服务多个 worker,那份开销本会摊到多个任务上
  • 口径说明(apscheduler):APScheduler 的定时作业模型,含作业登记与触发判定成本;该库会吞掉作业内异常,本档已在 drain 时重新抛出。口径说明:该库不提供作业完成通知,故完成信号由本档的 Condition 给出,每任务一次通知的开销计入其端到端
  • 口径说明(asyncio_pool):asyncio 事件循环调度同步执行体(等价于 loop.run_in_executor),非原生协程并发;与线程池的差别是事件循环自身开销
  • 口径说明(bare_thread):每任务派生一个 threading.Thread,无池化、无复用;线程创建成本计入端到端。收集执行体自报耗时用无锁的 list.append(GIL 下本身原子)——插桩不得给某一档加别档没有的成本,否则对照就成了插桩的对照
  • 口径说明(process_pool):ProcessPoolExecutor:执行体与返回值跨进程序列化的成本计入端到端,与多线程档位不可直接等价比较

数据:口径局限与偏差来源

口径局限与偏差来源

口径局限与偏差来源(续)

  • 口径说明(thread_pool):concurrent.futures.ThreadPoolExecutor,池大小 = 并发度;线程复用、无任务队列语义
  • 口径说明(zoo):端到端终点为「worker 完成并在飞表注销」;框架其后的结果投递按世代分流:上一代的投递路径是坏的(dispatch 按 reactor_name 而非主题查响应器,每次调用必抛),完成信号只能取自框架内部回调;当前代该处已修好,完成信号取自框架自己的结果响应器。口径说明:完成信号由本档的 Condition 给出,每任务一次通知的开销计入其端到端;该方向的偏差使被测框架看起来更慢,即对被测框架不利而非有利
  • 不给出开销数字的组:以下 (适配器, 并发度) 组的并发度超过这次运行所在机器的并行能力:执行体自报的耗时里含超订带来的调度等待,与「墙钟 / 并发度」不是同一件事,相减的结果没有意义(实测出现过负值,并衍生出无意义的变化倍数)。故本报告对它们不给框架开销、也不给交叉点;端到端、吞吐与执行体自报值仍然有效,原始留档里的字段也一个没删。判据取自环境自述的逻辑核数,另有一条证据性兜底:算出来的开销为负同样判为不可读——框架只会加时间不会减时间
  • 未参与判定的自检项:这些单元的执行体档位偏差未参与判定(并发度高于最低档,或档位短到墙钟受调度颗粒度支配)。原始值仍在场,但那两处的墙钟不足以断定校准是否正确——读这些档位的数字时要把它算进去

绝对耗时:仅在同一次运行内部有效,不可跨运行比较

数据:口径局限与偏差来源

zoo-bench 报告

加入你自己的对照

本 harness 的对照方案是开放的:实现 zoo_bench.adapters.BaseAdapter 的四个方法(setup / submit / drain / teardown),用 zoo_bench.adapters.registry.register 登记,或在 matrix.yaml 的 extra_modules 里列出你的模块路径——无需改动本仓库任何文件。你的实现会通过同一套等价性验证(提交 N 个执行体、断言全部执行且各执行一次),不通过的不会被采信。我们主动把这条路径写进报告:一份由被测框架维护者撰写、测量被测框架的报告,读者有理由怀疑对照被写慢或口径被挑选;让任何人能提交自己的对照,是这份报告可被质疑、也可被证伪的前提。

数据:加入你自己的对照

zoo-bench 报告

自检

  • 测量自检整体:通过
  • 进程隔离:{'parent_pid': 85458, 'child_pids': [85914, 85917, 85920, 85923, 85926, 85932, 85938, 85944, 85950, 85968, 85986, 86004, 86022, 86079, 86137, 86193, 86260, 86262, 86264, 86266, 86268, 86273, 86278, 86283, 86288, 86305, 86322, 86339, 86419, 86478, 86538, 86604, 86671, 86705, 86739, 86773, 86807, 86940, 87073, 87206, 87339, 87868, 88397, 88926, 89455, 91569, 93682, 95795, 97911, 97915, 97919, 97923, 97927, 97934, 97941, 97948, 97955, 97974, 97993, 98012, 98031, 98098, 98165, 98232, 98301, 98303, 98305, 98307, 98309, 98314, 98319, 98324, 98329, 98346, 98363, 98380, 98397, 98453, 98510, 98570, 98636, 98638, 98640, 98642, 98644, 986
  • 49, 98654, 98659, 98664, 98681, 98698, 98715, 98732, 98797, 98862, 98928], 'all_distinct': True, 'none_equals_parent': True}

数据:自检

附录

每一页都可在全文里逐字复核

幻灯片为了「一页一个结论」而压缩了篇幅;被压缩的只有排版,没有数值。

  • 逐单元明细(分位数、离散度、每轮原始样本):同目录的 report.md
  • 图表(SVG 与 PNG):同目录的 figures/,另见 report.pdf
  • 原始留档:results/zoo-framework-dev/20261011T094251Z.json
  • 本轮有效单元 96,失败单元 0

明细有一百多行,压进幻灯片等于让读者失去核对的手段。

← / → · space · R reset