4、vLLM性能日志解读:TTFT日志、TPOT日志、吞吐量日志、批处理大小日志
各位同学,今天我们来聊聊vLLM性能日志里最核心的几个指标。说实话,我刚开始接触vLLM的时候,面对满屏的日志也是一头雾水。后来踩了不少坑,才慢慢摸清楚这些数字背后的门道。
性能日志说白了就是模型的体检报告。TTFT、TPOT、吞吐量、批处理大小,这四个指标就像人的体温、血压、心率一样,缺一不可。你想想看,如果只看吞吐量不看延迟,那跟只看体重不看体脂率有什么区别?
核心观点:性能日志不是用来收藏的,是用来指导调优的。每个数字背后都藏着一个优化机会。
4.1 TTFT日志:首Token延迟
TTFT,全称Time To First Token。说白了就是用户发请求到收到第一个Token的时间。这个指标直接决定了用户体验——谁都不想等半天才看到第一个字蹦出来。
我在项目中遇到过一个问题:某次上线后用户反馈响应特别慢,一看TTFT日志,好家伙,从正常的200ms飙到了2s。排查下来发现是prefill阶段的计算资源被其他任务抢占了。
vLLM的TTFT日志长这样:
INFO 04-01 10:23:45 scheduler.py:456] TTFT: 0.234s | Request ID: req-001 | Prompt tokens: 512
解读这个日志,我一般看三个点:
- 绝对值:正常应该在100ms-500ms之间。超过1s就要警惕了。
- 波动情况:如果TTFT忽高忽低,说明系统负载不稳定。
- 与Prompt长度的关系:Prompt越长,TTFT自然越大。但如果是线性增长,那就有问题了。
我的小技巧:我会把TTFT日志单独抽出来画个时间序列图。如果发现某个时间点TTFT突然飙升,十有八九是发生了GC(垃圾回收)或者网络抖动。
4.2 TPOT日志:每个Token输出时间
TPOT,Time Per Output Token。这个指标衡量的是模型生成每个Token需要多长时间。嗯,这里要注意,TPOT和TTFT是两码事——TTFT看的是首Token,TPOT看的是后续Token的生成速度。
我曾经遇到过一个案例:某个模型TTFT表现很好,但TPOT特别慢。用户感觉就是「第一个字出来很快,但后面一个字一个字往外蹦,急死人」。后来发现是KV Cache的显存分配出了问题。
典型的TPOT日志:
INFO 04-01 10:23:46 scheduler.py:512] TPOT: 0.045s | Request ID: req-001 | Output tokens: 128
解读要点:
- 理想值:对于7B模型,TPOT应该在20ms-50ms之间。13B模型在50ms-100ms。
- 稳定性:TPOT应该相对稳定。如果波动超过30%,说明显存带宽可能成为瓶颈。
- 与Batch Size的关系:Batch Size增大,TPOT会上升。但如果上升太快,说明显存带宽不够用了。
避坑指南:我曾经被TPOT的「假象」骗过。有一次TPOT看起来很正常,但实际用户体验很差。后来发现是因为TPOT只统计了decoder阶段的时间,而prefill阶段的耗时被算到了TTFT里。所以一定要结合两个指标一起看。
4.3 吞吐量日志:Tokens/秒
吞吐量,就是系统每秒能生成多少个Token。这个指标直接决定了你的服务能支撑多少并发用户。说白了,吞吐量上不去,用户一多就排队。
vLLM的吞吐量日志通常这样记录:
INFO 04-01 10:24:00 metrics.py:234] Throughput: 1250 tokens/s | Requests: 8 | Avg batch size: 4
我一般这样分析吞吐量:
- 看趋势:吞吐量是上升还是下降?如果持续下降,可能有内存泄漏。
- 看峰值:峰值吞吐量决定了系统的上限。我习惯记录每天的峰值,看看有没有退化。
- 看与并发数的关系:并发数增加,吞吐量应该先升后降。如果一直降,说明系统设计有问题。
| 并发数 | 吞吐量(tokens/s) | 平均延迟(ms) | 结论 |
|---|---|---|---|
| 1 | 500 | 200 | 基线正常 |
| 4 | 1800 | 450 | 线性扩展 |
| 8 | 2500 | 800 | 接近瓶颈 |
| 16 | 2200 | 1500 | 过载,吞吐量下降 |
关键认知:吞吐量和延迟是跷跷板。一味追求高吞吐量,延迟就会飙升。我个人的经验是,找到「吞吐量拐点」——就是再增加并发吞吐量也不涨的那个点,然后留20%的余量。
4.4 批处理大小日志:动态Batch Size
批处理大小,Batch Size,是vLLM性能调优的核心参数。vLLM最牛的地方就是支持动态批处理——不用等所有请求都到齐再处理,而是来一个处理一个,边处理边合并。
批处理大小日志长这样:
INFO 04-01 10:24:01 scheduler.py:678] Batch size: 6 | Running: 12 | Waiting: 3 | Swapped: 1
解读这个日志,我重点关注:
- 当前Batch Size:理想情况下,应该接近你设置的max_num_seqs。如果一直很小,说明并发不够或者调度策略有问题。
- Running vs Waiting:如果Waiting队列一直很大,说明处理速度跟不上请求速度。
- Swapped数量:这个很关键。Swapped表示被换出到CPU内存的请求。如果Swapped>0,说明显存不够用了。
我的调优经验:我曾经遇到一个场景,Batch Size始终上不去,最大只有2。排查了半天,发现是max_num_seqs设得太小。但调大之后,显存又爆了。最后通过调整gpu_memory_utilization和max_num_seqs的配比,才找到平衡点。
4.5 四个指标的综合解读
单独看一个指标意义不大,四个指标要放在一起看。我总结了一个「四维分析法」:
- TTFT高 + TPOT正常:问题出在prefill阶段。检查Prompt长度、显存带宽。
- TTFT正常 + TPOT高:问题出在decoder阶段。检查KV Cache、显存容量。
- 吞吐量低 + Batch Size小:并发不够或者调度策略保守。考虑增加并发或调整调度参数。
- 吞吐量低 + Batch Size大:单个请求处理太慢。检查模型推理效率。
你想想看,如果只盯着吞吐量看,发现它下降了,你根本不知道是并发不够还是模型变慢了。但结合Batch Size一看,就一目了然了。
重要提醒:不要只看平均值。我习惯把P99和P50分开看。有一次P50的TTFT只有200ms,但P99达到了3s。这说明有少数请求被严重延迟了,可能是被大请求阻塞了。这种问题只看平均值根本发现不了。
好了,关于性能日志的解读就讲到这里。这些指标就像汽车的仪表盘,每个都有它的意义。关键是要学会综合判断,而不是孤立地看某个数字。下次遇到性能问题,记得把这四个指标拉出来对比分析,问题往往就藏在这些数字的关系里。