perf_runner 设计
设计目标
moon bench 报告的是汇总结果;而仓库的报告流水线需要单个用例的逐样本原始计时,自行控制重复次数和预热,还需要一种重放用例并检查其结果的方式。perf_runner 就是这样的单用例工具。
数学背景
一个样本是 repeat 次连续调用的平均时间,。在样本内部取平均,可以把每次测量固定的计时器分辨率误差减小为原来的 1/repeat,并把独立的单次调用噪声减小为 。在样本之间,流水线使用顺序统计量(中位数、p90)和 MAD,它们对调度造成的离群值是稳健的。预热轮次会丢弃最初几次调用的瞬态(缓存、分支预测器、惰性初始化)。
设计决策
在计时器之外制作 scratch 副本
对于会修改输入的用例,repeat 份副本会在 monotonic_clock_start 之前准备好,因此复制不计入测量,且每次调用看到的输入相同。
每种模式都有校验和
每次调用的校验和都被折叠进一个累计值,使工作保持可观察,诊断模式也能据此验证结果逐位相同。
纯 JSON 行
输出是每次运行一个 JSON 对象,通过字符串拼接组装,这使 runner 无需序列化依赖,也便于用 Python 解析。
正确性与不变量
- 在诊断模式下,打印的校验和等于各次调用校验和的 FNV 风格折叠,这由该包的白盒测试验证。
- 为 scratch 用例制作的副本从不与已准备的输入互为别名。
被否决的方案
- 为每次调用单独计时。 亚微秒级的调用低于时钟分辨率;
repeat将其分摊。
边界
runner 每个进程只测量一个用例,自身不计算统计量,并且只支持在 perf_support 中注册的用例。