文档目录

5.7 噪声底线与回归检测

上一节:5.6 统计基础 | 下一节:5.8 实验记录与常见反模式 配套代码:05-experiment-design/07-noise-floor-and-regression 本节是本章的核心。 它回答一个问题:在你的环境里,多大的差异才算「真实差异」?


一句话结论

噪声底线 = 在代码完全不变的情况下,你重复实验能得到多大的差异。 它是你判断一切性能结论的标尺:低于噪声底线的"优化",无论听起来多合理,都无法被你的数据证实。


一、用「体重秤的精度」理解噪声底线

你家的体重秤有 ±0.5 kg 的误差。今天称是 70.0 kg,明天是 69.7 kg。

你能说「我减了 0.3 kg 吗?

不能——因为 0.3 kg 小于秤的精度。

正确说法:「在秤的精度范围内,体重没有变化。」

性能实验完全一样:

如果你的环境噪声底线是 ±8%:
  P99 从 210ms 到 198ms(-5.7%) → ❌ 无法确认
  P99 从 210ms 到 150ms(-28.6%)→ ✅ 可以确认

关键:噪声底线不是「你可能做到多精确」,而是「你的工具实际有多精确」。它由环境(云主机、后台任务、GC 抖动)决定,不由你的意愿决定。


二、怎么测噪声底线(六步)

① 冻结一切:代码、数据、负载、环境、观测配置全部不变
② 重启服务(确保从同一初始状态开始)
③ 完整跑一次实验(含预热),记录 P50/P95/P99、QPS、错误率
④ 重复 5–10 次(每次都重启 + 预热)
⑤ 计算每个指标的均值、标准差、CV
⑥ 定义噪声底线 = 该指标的最大波动范围

关键要求

要求 为什么
代码一字不改 否则测的不是噪声
每次都重启服务 否则上一轮的热状态会影响下一轮
至少 5 次 3 次看不出分布形态,5 次能看出基本范围
记录每一轮的值 不只看 CV,还要看是否有趋势(是否在变好/变坏)

输出示例

═══ 噪声底线测量(10 轮,代码未改动)═══

轮次  QPS     P50    P95    P99    错误率
   1  498.2   32.1   68.4   93.2   0.00%
   2  499.1   33.0   70.2   96.1   0.00%
   3  497.5   32.4   67.9   94.0   0.00%
   4  498.8   34.2   74.1  103.5   0.00%   ← 偏高
   5  499.4   32.8   69.3   95.2   0.00%
   6  498.0   32.5   68.8   94.4   0.00%
   7  499.7   33.1   70.5   96.8   0.00%
   8  498.3   32.9   69.1   95.0   0.00%
   9  499.2   32.6   68.2   93.8   0.00%
  10  498.6   33.3   71.0   97.2   0.00%

指标   中位数   最小值   最大值   波动范围   CV
QPS    498.8   497.5   499.7    ±0.22%    0.13%
P50     32.8    32.1    34.2    ±3.2%     1.8%
P95     69.2    67.9    74.1    ±4.5%     2.7%
P99     95.1    93.2   103.5    ±5.4%     3.1%

═══ 结论 ═══
噪声底线(取最大波动范围的 1.5 倍作为安全边际):
  QPS : ±0.3%
  P50 : ±5%
  P95 : ±7%
  P99 : ±8%

含义:低于以下差异的结论,在本环境中不可信:
  优化声称 P99 改善 < 8%  → 无法确认
  优化声称 P50 改善 < 5%  → 无法确认

三、噪声底线的三个用处

用途一:判断「优化是否可信」

优化前 P99 中位数 = 210 ms
优化后 P99 中位数 = 195 ms
差异 = -7.1%

噪声底线 = ±8%

结论:❌ 差异在噪声范围内,无法确认优化有效

注意:这不是说「优化无效」,而是说「你的数据不足以证明它有效」。可能需要:

  • 增加轮数(降低统计误差);
  • 改善环境(降低噪声);
  • 或者寻找差异更大的优化点。

用途二:设定 CI 门禁阈值

第 8 章会用到:

门禁阈值 = 噪声底线 × 安全系数(通常 1.5–2)

例:噪声底线 ±8% → 门禁阈值设为「恶化超过 12% 才告警」

为什么不能设成噪声底线本身:那样会有 50% 的误报率(噪声正好跨过阈值)。

用途三:判断「环境是否可用」

如果 CV > 10%:
  → 环境不适合做精细的性能对比
  → 先解决环境问题(第 4 节),或只做大颗粒度的判断(> 30% 的差异)

四、一个必须警惕的现象:趋势漂移

10 轮数据如果呈现单调趋势(比如 P99 一直在缓慢上升),那不是噪声——那是环境在变化:

轮次:  1     2     3     4     5     6     7     8     9    10
P99:  93.2  94.1  95.0  95.8  96.5  97.2  98.0  98.9  99.5 100.2
      └──────────────── 持续上升 ────────────────┘

可能原因:

原因 怎么确认
数据量在增长(压测写了数据) 检查表行数
缓存逐渐被污染/驱逐 检查命中率趋势
内存泄漏 检查堆基线趋势(第 3 章 3.5)
机器发热降频 检查 CPU 频率
其他服务开始占用资源 检查系统负载

处理:先解决漂移,再测噪声底线。有漂移的环境测出的噪声底线是不可信的。

另一种漂移:如果做了写操作,数据量会持续增长——这是压测设计问题(第 4 章 4.1 节提到的数据隔离)。


五、回归检测:把噪声底线变成门禁

什么是回归检测

每次代码变更后,自动对比性能指标与基线:
  如果指标恶化超过阈值 → 告警/失败
  否则 → 通过

这是第 8 章「持续化」的基础,而阈值必须来自噪声底线。

回归检测的三个设计要点

要点 说明
相对比较,不是绝对阈值 与仓库中的基线比,而不是硬编码的数字
阈值 = 噪声底线 × 1.5–2 阈值必须高于噪声,否则天天误报
只对稳定指标设门禁 max、P999 波动太大,只做趋势观察

一个真实的误报代价

阈值设置不当(等于噪声底线):
  → 每天 3–5 次误报
  → 工程师开始认为"这个门禁不可信"
  → 出现真问题时也无人处理
  → 门禁实际上已经失效

结论:宁可漏报,不可误报。

六、从噪声底线到「最小可检测差异」

最小可检测差异(MDD)≈ 噪声底线 × 2

理由:
  优化前的值本身有 ±N 的噪声
  优化后的值本身也有 ±N 的噪声
  两者相减,噪声可能叠加到 ±2N

所以:

噪声底线 ±8%
→ 最小可检测差异约 16%

含义:只有声称"改善了 16% 以上"时,你的数据才有足够的说服力。
      声称 10% 的改善,可能是真的,但你的环境证明不了。

这是一个残酷但重要的数字:如果你的环境噪声底线是 ±8%,那么所有 10% 以内的优化,你都只能"相信"而不能"证明"。

怎么办(三个方向):

方向 做法 代价
降低噪声 独占机器、绑核、固定频率、减少后台任务 环境成本
增加样本 多轮实验 + 统计检验 时间成本
增大效应 找差异更大的优化点(通常是更上游的瓶颈) 需要重新定位

通常第三个方向最有效:与其纠结 5% 的常数优化,不如去找那个占 P99 50% 的环节(第 1 章 1.3 节的延迟分解)。


七、本节小结

  1. 噪声底线 = 代码不变时重复实验的差异范围。它是判断一切性能结论的标尺。
  2. 测量方法:冻结一切 → 重启 → 完整跑 → 重复 5–10 次 → 算 CV 与波动范围。
  3. 低于噪声底线的"优化"无法被你的数据证实——这不是说它无效,而是说你证明不了。
  4. 最小可检测差异 ≈ 噪声底线 × 2(因为两组数据相减,噪声叠加)。
  5. 噪声底线有三个用途:判断优化可信度、设定 CI 门禁阈值(×1.5–2)、判断环境是否可用。
  6. 警惕趋势漂移(10 轮单调上升)——那不是噪声,是环境在变,必须先解决。
  7. 门禁设计原则:宁可漏报,不可误报。

八、自测

  1. 你的环境噪声底线是 ±8%(P99)。一个优化声称把 P99 从 210 ms 降到 190 ms(-9.5%)。你该怎么表述这个结论?
  2. 你在测噪声底线时发现 10 轮的 P99 从 93 ms 单调上升到 100 ms。这说明什么?你会怎么处理?
  3. 为什么 CI 门禁的阈值要设成「噪声底线 × 1.5–2」,而不是直接等于噪声底线?
  1. 正确的表述:「观测到 P99 从 210 ms 变化到 190 ms(-9.5%),略高于本环境 8% 的噪声底线,但小于最小可检测差异(约 16%)。因此这个改进方向是可信的,但幅度需要在更干净的环境中验证。」 关键点:① 不要直接说「提升 9.5%」——那是把噪声当成果;② 也不要全盘否定——9.5% > 8%,有一定证据;③ 建议的下一步:增加轮数(比如 10 轮)、或用更精确的指标(比如对比 P50 或 QPS,它们的噪声可能更小)、或在更干净的环境重测;④ 如果这个优化成本很低(比如改一行配置),可以先采纳并继续观察;如果成本高(引入新组件),应该先验证幅度。
  2. 这说明环境在漂移,不是噪声。噪声的特征是「随机波动、无明显趋势」,而单调上升说明有系统性因素在累积。可能原因与处理:① 数据量增长(压测写了数据)——处理:检查表行数,给写操作加数据隔离或清理;② 缓存逐渐被污染/驱逐——处理:看缓存命中率趋势;③ 内存泄漏——处理:看堆基线趋势(第 3 章 3.5 的浸泡分析方法);④ 机器降频/发热——处理:检查 CPU 频率;⑤ 其他服务开始占用资源——处理:看系统负载与 st。处理原则:有漂移的环境测出的噪声底线不可信,必须先消除漂移,再重测。
  3. 因为阈值等于噪声底线会导致约 50% 的误报率——噪声是随机波动,正好跨过阈值的概率很高。具体来说:如果噪声在 ±8% 内均匀波动,那么「优化后的值」有相当大概率落在基线 −8% 之外(看起来"改善"了),也有相当大概率落在 +8% 之外(看起来"恶化"了)。乘 1.5–2 的含义:把阈值设在噪声的 1.5–2 倍处,只有超出正常波动范围的变化才触发告警——这样误报率会降到可接受水平(通常 < 5%)。代价是漏报:一个 10% 的真实退化如果没超过 12% 的阈值,就不会告警。但这个取舍是必要的——门禁如果天天误报,工程师就会忽略它,门禁实际上失效,比没有门禁更糟(因为它给人虚假的安全感)。