Hey百分位算法解析:一次线性扫描如何算出10/25/50/75/90/95/99七个分位点 Hey百分位算法解析一次线性扫描如何算出10/25/50/75/90/95/99七个分位点【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/heyHey 是一个用 Go 编写的 HTTP 压测工具ApacheBench 的现代替代压测结束后会输出一份Latency distribution列出 10/25/50/75/90/95/99 七个分位点的延迟。 本文带你拆解它的百分位算法为什么只写一个 for 循环、一次线性扫描就能把所有分位点全部算出来。一、先认识 hey一款 HTTP 压测小工具hey 的定位非常简单向你的 Web 服务发送 N 个请求可用-n、并发-c、QPS 限速-q然后统计吞吐量和延迟分布。跑完压测报告里最有价值的部分不是平均值而是分位延迟——它直接回答百分之 X 的请求在多久内完成。二、为什么压测要看分位点平均值是最容易骗人的统计量。举个典型场景1000 个请求中990 个在10ms内返回10 个因为 GC 停顿花了200ms平均值 ≈ 21.9ms看起来还行但 P99 ≈ 200ms说明每 100 个用户就有 1 个体验到明显卡顿所以 hey 默认报告 7 个分位点P10、P25、P50中位数、P75、P90、P95、P99覆盖从大多数请求到极端长尾的完整画像。三、核心算法一次线性扫描算出 7 个分位点算法实现只有十几行位于 latencies() 函数pctls : []int{10, 25, 50, 75, 90, 95, 99} data : make([]float64, len(pctls)) j : 0 for i : 0; i len(r.lats) j len(pctls); i { current : i * 100 / len(r.lats) if current pctls[j] { data[j] r.lats[i] j } }整个算法只有 3 个设计要点逐个拆解 3.1 前提延迟数组已经排好序r.lats是压测期间由各 worker 通过 channel 汇总上来的总延迟切片见 runReporter 的收集循环输出前会先执行sort.Float64s(r.lats)排序report.go#L182。排序后第 P 百分位就变成一道下标问题从左往右走找到第一个它前面的元素占比 ≥ P%的位置即可。3.2 双指针 整数除法零浮点开销循环里两个指针分工明确i当前扫到的元素下标数据指针j当前要填的分位点序号目标指针初始指向 P10关键一行是current : i * 100 / len(r.lats)这是整数除法i*100/n向下取整模拟出元素 i 所处的百分位刻度每步只做 1 次乘法 1 次整数除法 1 次比较没有浮点运算缓存友好当current pctls[j]到达下一个目标刻度时把lats[i]记为该分位点j指向下一个目标这正是统计学中的最近秩法nearest-rank第 P 百分位 排序后第 ⌈P/100 × n⌉ 小的值。3.3 手算示例n 100 时指针怎么走分位点触发条件i*100/100 ≥ p命中的元素P10i ≥ 10lats[10]P25i ≥ 25lats[25]P50i ≥ 50lats[50]P75i ≥ 75lats[75]P90i ≥ 90lats[90]P95i ≥ 95lats[95]P99i ≥ 99lats[99]两个指针各自只前进、从不回退7 个分位点在一次遍历中按顺序全部路过命中。3.4 两个容易被忽略的细节提前退出循环条件是j len(pctls)。填满 7 个点后立即终止——P99 大约在 99% 处触发所以最后 1% 的尾部数据根本不用扫。样本太少自动省略末尾有if data[i] 0的过滤report.go#L229-L233。例如只发 10 个请求时i*100/10最大只到 90P95/P99 永远不会被触发报告会自动省略这两行而不是显示误导性的 0。复杂度账本排序 O(n log n) 扫描 O(n)。对比每个分位点单独算一遍或引入复杂数据结构的做法单遍扫描以最小常数把 7 个点一次算完这正是 hey 作为轻量级压测工具的典型取舍。四、结果如何呈现算出的[]LatencyDistribution会被塞进报告快照由默认模板渲染print.go#L110-L111这就是你压测结束时看到的段落Latency distribution: 10% in 0.0012 secs 25% in 0.0015 secs 50% in 0.0021 secs 75% in 0.0030 secs 90% in 0.0048 secs 95% in 0.0062 secs 99% in 0.0095 secs另外注意为控制内存hey 最多只保存 100 万个样本参与统计maxRes 常量超过部分计入总数但不再进入分位计算。五、小结✅排序 单遍扫描分位点问题被化简为找下标O(n) 一遍出结果✅整数除法模拟刻度i*100/n p一步到位无浮点、无额外内存✅双指针各自单调前进7 个分位点顺序命中天然支持提前退出✅边界自洽样本不足时高百分位自动省略数据有 100 万上限保护下次跑完 hey 看到 P99 飙升时你不仅知道该排查长尾也清楚这个数字是怎么从一次线性扫描里路过得来的。【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/hey创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考