第 9 章 评测:怎么证明你选对了
先修:第 1–8 章 · 深度:L2 · 预计阅读:30 分钟
一句话:平均值是给汇报看的,P99 和 goodput 是给用户看的。
一句"我们 TTFT 200 毫秒"
老板问:多少人并发下的 200 毫秒?第九十九个人的首字是多少?
两个问题都答不上来,这个数就没意义。
压测的难点不在工具,在口径。口径不定,两个人测同一个服务能差出三倍。
五个数,各管一段
首字延迟(TTFT):从请求发出到看见第一个字。包含排队、prefill、首字采样。
出字间隔(TPOT):第一个字之后,平均每个字花的时间。它的倒数是单条的出字速度。
分位数(P95、P99):把延迟排序,第 95% 和第 99% 位置的值。它衡量最难受的那批人。
有效吞吐(goodput):在满足 SLO 的前提下,单位时间服务多少请求。SLO 是"TTFT 小于 2 秒且 TPOT 小于 50 毫秒"这类硬指标。
每 token 成本:一台 GPU 每小时多少钱,除以它在那小时里产出的有效 token 数。
前三个衡量体验,后两个衡量值不值。
goodput 为什么比吞吐诚实
假设你的服务每秒吐 411 个 token,看着很强。
但二十个请求里有六个在排队,它们的首字超过 5 秒,超出了 SLO。这六个不算数。
有效吞吐是 14 条完成、6 条超时,那 goodput 就是 411 × 14/20,约 288 token/s。
吞吐高、goodput 低,说明你的产能花在了让一部分人满意、另一部分人骂人上。
这个词存在的理由就是:它不允许你把超时的人算进成绩里。
压测怎么设计
四个参数,缺一个结果就不可信。
输入长度分布。不要只测一个长度。按真实分布来:八成两百字,两成 8K 合同。只测 8K 会低估吞吐,只测两百字会低估容量压力。
输出长度分布。同理。输出长度直接决定每条请求占多久槽位。
到达方式。一次性全发,测的是爆发;按固定速率发,测的是持续负载;按泊松分布发,最接近真实。三种都要看。
持续时长。至少跑十分钟,等预热过去、队列进入稳态。跑三十秒测出来的数,通常是缓存和连接池还没热的状态。
四个容易造假的测法
只报平均延迟。二十个人里六个人等五秒,平均值可能还是 1.2 秒。
空载测。batch=1、并发=1,测出来的 TPOT 最好看,也是最不真实。你的用户不会排队来。
缓存全命中。用同一段 prompt 反复打,前缀缓存全生效,测出来比真实好一大截。换一批不同 prompt 再测。
batch 没拼上。参数设了 14 并发,实际每个请求都串行跑完,你以为测的是 batch 14。压测时要同时记录 running batch 的实测值。
这四个都做过,再谈优化。
成本怎么算
成本的结构是:GPU 小时数 × 每小时价格 ÷ 有效 token 数。
三个变量都能动手:换个便宜档的卡、提高利用率、提高 goodput。
第三项最容易被忽略。同一个服务,goodput 从 288 提到 380,成本直接降三成,没换任何硬件。
反过来,只看"每百万 token 多少钱"这个数,不看它是在什么并发、什么 SLO 下测的,等于拿两个不同口径的数比大小。
什么时候这些指标不够用
流式对话里,用户对"出字是否均匀"比平均 TPOT 更敏感。TPOT 30 毫秒但每十个字卡一下,体感比稳定 50 毫秒还差。
多轮对话里,第二轮的 TTFT 受前缀缓存影响很大,单轮的测试完全不反映它。
长上下文里,答案质量本身要评,光看速度会选出一个又快又错的方案。
这几种情况都需要补充指标,不能只靠这五个数。
经验:先把 SLO 写在纸上
压测之前,先写下三条:TTFT 上限、TPOT 上限、可接受的超时比例。
写完再测。没有这三条,测出来的数字没法判断好坏,只能拿去汇报。
练习
六道题,先闭卷,再翻 ANSWERS.md。
- 吞吐 411 token/s、20 条里 14 条达标,goodput 是多少?
- 为什么只测 batch=1 会高估服务能力?
- 前缀缓存全命中时,哪两个指标会好看得不真实?
- 找错:"平均 TTFT 1.2 秒,说明服务达标。"
- 你要比较两个引擎,压测脚本必须固定哪四件事?
- 给自己的服务写一份压测方案,包含长度分布、到达方式、时长和三条 SLO。
这一章就记一句
五个数各有分工:TTFT、TPOT、P99 看体验,goodput 和每 token 成本看值不值。goodput 只统计达标的请求,所以它比吞吐诚实。
真只记一句:压测的可信度取决于口径,不取决于工具;长度分布、到达方式、持续时长、实测 batch,四个里缺一个,结论就可以被推翻。
下一章把这本书所有的账合成一次完整的判断。