平均值毫无意义。

我最近尝试验证一些与以下性能相关的改进lld在$DAYJOB看到基准测试有所提升,但实际生产仪表盘却没有改善,这让人有些沮丧。

我之前有网络服务背景,习惯了查看单个时间序列仪表盘,有时超过几个百分位数,我期待看到明显变化,但数据似乎太杂乱,无法下结论。

原来有同事在评估构建速度改进时也遇到过类似问题。有很多变量会影响构建:冷缓存、增量缓存、本地缓存、远程缓存等,构建时间会因系统状态和工作负载而有很大差异。

她最终利用累积分布函数(CDF)来可视化数据,这对我来说是个启示。

这促使我探索了除了CDF之外的其他数据可视化方式,以及单张图像或统计数据往往不足以讲述全部情况。这篇文章将介绍一个合成展示了不同的可视化如何讲述同一数据的不同故事。

目标是说服你看关注你的数据,而不是用一个数字来概括。

以下内容均来自一个带有固定种子的合成数据集。完整剧本可见大致如此.它是一个单一文件,带有nix-shell所以只要你用,就能精确复刻每一个模型什么都没有.

注释我利用人工智能帮助生成本文中的数据和图表。如果这让你不舒服,抱歉。🤷

那次“让情况更糟”的推广

设置是这样的:我们运营一个典型的网络服务,并在一周内推出了新的缓存层,希望能减少请求延迟。

该更改已完全部署,绘制延迟仪表盘意思看起来像这样:

平均延迟消失了上,从112毫秒提升到122毫秒。 ☹️

如果删减了SEV,我们会恢复变更并写事后分析。右?🤔

一个数字,四层楼

尤其是网络服务,通常会关注不同的百分位,尤其是分布的尾端,比如p95和p99。

统计量 之前 之后 变革
意思 112毫秒 122毫秒 +9%
第50页(中位数) 99毫秒 54毫秒 −46%
第95页 224毫秒 454毫秒 +103%
第99页 309毫秒 678毫秒 +119%

现在我们有个问题,问题是大家都说得对.均值表示变化是轻度回归。中位数(第50页)说这次变动是个大胜利,典型的请求得到了速度几乎是它的两倍.p99显示是SEV,最糟糕的请求会翻倍以上。

均值和中位数由相同数值计算,指向相反方向.

工程师通常被教导要以数据为导向,但往往很容易挑选支持你论点的统计数据。

看看形状

你对分布的下一个基本功能是绘制其形状。以下是两种延迟分布,分别为前后分布,作为密度:

就是它。🤓☝️ “之前”是一个整齐的隆起.“之后”是两个隆起.

这已经解释了之前的矛盾,但要正确理解还是有点棘手。形状取决于我们选择的平滑参数,两个填充在重叠处会互相混淆,而且很难读懂百分位数脱掉了。

我能看到有两个群体;我不太清楚中间隔离带去了哪里。

你没用的最佳图表

累积分布函数(CDF)一次回答每个百分位的一个问题:有多少请求是或更低的x毫秒?

CDF是可视化单张图表中多个百分位数的非常简单方法。根据曲线的不同,我们可以理解请求延迟在整个群体中的分布。

我发现将“之前”和“之后”的CDF绘制在同一张图表上,可以比较它们的效果,非常有用。然后你可以可视化不同百分位的变化,理解变化如何影响整个人群。

在我们的报道中,请求延迟低于140毫秒时,“之后”曲线已经向左移动。这意味着更多的请求比以前更快完成。“后期”曲线比右侧的“前期”曲线高,约为140毫秒,这意味着更多请求完成速度比之前慢。

两条曲线在~140毫秒处交叉,这是变化从胜利转为失败的临界点。

提示两个交叉的CDF是变化的无可误认的标志,没有单一百分位能总结,因为效应的符号取决于你问的哪个百分位数。

谁赢了,赢了多少

CDF告诉我们那效果会变化符号:更快或更慢。显而易见的下一个问题是多么多,分布中的每一点。我们可以绘制每个百分位数p,后延迟减去前延迟,称为移位函数.

零线以下变化更快;在上面,慢一点。我们可以直观地看到每个百分位的变化幅度。

倒退一直都在

到目前为止,我们看了两张冻结的快照,分别是前后。不过,推送往往不是瞬间完成的。在本报道中,我们用一周时间推送了新的缓存层,流量从0%提升到100%。

各自做了什么一天长什么样?每天叠加一个分配,你得到的是一个山脊线:

我们现在可以直观地看到随着时间出现的回归。随着推展推进,我们可以看到主要峰值(快速请求)向左滑动,右侧出现第二个峰值(慢请求)。

中位数在下降,但慢速请求数量和延迟却在悄然增长。

这里的x轴是对数轴。延迟大致为对数正态,线性轴上快速峰值是一个高尖峰,旁边是一个隐形的涂抹;对数轴让两个驼峰都读作驼峰。

我们可以做类似的事情,把它压缩到一个网格里,作为热力图.每天一列,颜色显示每个延迟时流量的流量:

你隐约能看到一个新群体正在出现。

任何对整周的总计算都会把这七个截然不同的天合并成一个模糊的数字,完全掩盖了趋势。

双峰是有原因的

我们现在已经彻底确立了什么发生了。下一个问题是为什么.这实际上与$DAYJOB我必须按二进制大小(即>50MiB)切割数据,以观察延迟分布的双峰性。

在我们的故事中,新层要么满足缓存请求(a击中)或通过额外跳跃(a)直接传入后端小姐).我们可以按该属性将“之后”请求拆分,并为每个请求绘制一个CDF:

根据缓存结果,每个群体再次是单峰的。

我们很容易看到那个缓存热门歌曲当它们向左移动时,速度比旧基线快。

缓存失误多花钱跳跃,落地偏右。

为什么那些请求?

“有些请求漏掉缓存”是一种机制,但还不是原因。也就是请求未中,为什么?

每个请求都包含一个我还没用过的字段:它的响应规模.

缓存存储小型、高温的物体;大号的会被淘汰或者永远不合适。我们可以将延迟与响应大小绘制出来,并根据缓存命中还是未成功来标记每个点。

我们还可以在每个边际添加密度,以观察两族群沿各轴的分布情况:a联合图:

我们可以看到两个干净的群体群:快速小(缓存命中率)和大而慢(缓存未命中)。很明显,延迟分布中的双峰性是由响应大小分布中的双峰性引起的。

我们现在有了可操作的方案:提高缓存的最大对象大小,或者拆分大响应。🔥

一个图值一千个数字

通常,单个面板或图表太小,最多只能讲述全部故事。最坏的情况是,可能会产生误导。对同一数据有多个视角有助于理解完整情况。

我尤其对CDF能在一张图表中传达整个分布方式印象深刻,尤其是在比较看似......

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论