LLM延迟:TTFT与token间隔

黎 浩然/ 10 10 月, 2026/ 大语言模型/LARGELANGUAGEMODEL/LLM, 机器学习/MACHINELEARNING, 研究生/POSTGRADUATE, 计算机/COMPUTER/ 0 comments

流式回答很快出现第一句话,后面却停顿;另一个服务开始得慢,开始以后却输出得很顺。只看总耗时,很难区分这两种体验。首token延迟与后续token间隔应分开记录。

先把测量边界写清楚

在客户端,设发出请求的时间为t0,第一个真实内容token到达时间为t1,最后一个为tn。我们定义TTFT=t1−t0,末token延迟=tn−t0,后续平均间隔=(tn−t1)/(n−1),要求n至少为2。这里只有一个token时,后续间隔没有定义,不应伪造为0。

发出请求:0秒
首token:0.6秒
后续:0.8、1.0秒
末token:1.5秒
原创到达时间轴,使用人工构造时间戳;每个事件在这里代表一个token。

这是本文的客户端定义,并不自动等于推理服务器内部的计时口径。vLLM官方指标分别提供首token、token间隔和端到端延迟统计。接入监控前应确认版本与测量边界,包括排队、网络和响应结束事件是否被计算。

平均值怎样掩盖停顿

图中TTFT是0.6秒,末token延迟1.5秒。后续间隔约为0.2、0.2、0.5秒,平均0.3秒。平均数看起来稳定,却掩盖了最后一次更长的等待;因此还要看单次请求的间隔和整体分布。

from math import isclose

def measure(start, arrivals):
    if not arrivals or arrivals[0] < start or any(b<a for a,b in zip(arrivals,arrivals[1:])):
        raise ValueError('invalid timestamps')
    gaps = [b-a for a,b in zip(arrivals,arrivals[1:])]
    return arrivals[0]-start, arrivals[-1]-start, gaps, (sum(gaps)/len(gaps) if gaps else None)

ttft, end, gaps, mean_gap = measure(0, [.6,.8,1.,1.5])
assert isclose(ttft,.6) and isclose(end,1.5)
assert isclose(mean_gap,.3) and isclose(max(gaps),.5)
assert measure(0,[.6])[3] is None
print('TTFT:', ttft, 'last-token latency:',end)
print('gaps:',gaps, 'mean:',mean_gap)

代码已经执行,验证首token、末token、平均间隔、最大间隔与单token边界。实际网络数据块可能包含多个token,不能把一次流式回调天然当成一个token。若只有数据块时间,应明确命名为块间隔,避免伪装成token指标。

优化要对应等待发生的位置

首token慢,可以继续分解排队、输入处理和传输;后续间隔长,则检查生成过程、调度与客户端缓冲。不能仅凭这两个数字就断定某个组件故障,还需要服务端证据。

比较部署方案时固定输入长度、输出长度、并发与缓存状态,并报告尾部延迟及失败请求,避免只挑成功的短回答。端到端时间也可能包含末token之后的收尾工作,和本例的“末token延迟”要区分。

前缀缓存可能改善输入阶段,但不会自动消除每一次输出停顿。先确定改善的是哪个指标,再讨论用户体验是否变好。

English version

参考资料

Official documentation

补发说明:实际补发日期为北京时间2026年10月10日,文章日期保留原计划2026年10月10日14:00。代码为原创教学验证,没有运行真实模型性能测试。

支持

如果这篇文章对你有帮助,欢迎支持本站。

微信支持二维码,点击查看大图
微信
支付宝支持二维码,点击查看大图
支付宝
Buy Me a Coffee,点击支持本站
Buy Me a Coffee

二维码可点击放大。更多支持方式见支持页面。

Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*