大促流量一来,大模型服务就卡——推理性能压测

举报
霍格沃兹测试学社 发表于 2026/08/19 11:31:35 2026/08/19
【摘要】 本文揭秘大模型性能测试核心差异:告别传统QPS/RT,聚焦TTFT(首字延迟)、TPOT(逐字间隔)等流式指标。通过真实大促事故(首字延迟从0.8秒飙至15秒),剖析容量规划缺失、KV cache打满、无降级等痛点,并给出阶梯压测、拐点识别、混长文本等实战方法,助你应对AI面试高频题。

AI 测试开发面试高频题:“大模型服务怎么做性能测试?和传统压测有什么区别?”
传统接口压测看 QPS 和 RT,大模型压测看的是"用户等多久看到第一个字、每个字隔多久蹦出来"。指标体系换了,容量模型也换了。这篇用一次大促事故讲清楚。

一、真实事故:首字延迟从 0.8 秒飙到 15 秒

某电商智能导购,平时首字延迟 0.8 秒,体验丝滑。大促零点流量涨了 10 倍,监控曲线立刻变形:TTFT(首 token 延迟)从 0.8 秒飙到 15 秒,用户发完问题盯着空白对话框等十几秒,然后骂骂咧咧关掉;更惨的是部分请求排队超时直接 504,重试又加倍了流量,恶性循环。

事后排查,三个问题叠加:一是没做过容量规划,上线时的并发水位全凭拍脑袋;二是推理服务没设并发限制,高并发下 KV cache 被打满,continuous batching 频繁抢占,单请求生成速度(TPOT)也跟着恶化——不只是等得久,连"出字"都变慢了;三是没有降级预案,模型卡死时连一句"稍后再试"都给不出。

复盘会上性能负责人说了一句大实话:这不是模型不行,是我们从来没按大模型的方式压过它。

二、核心代码:流式压测器 + 阶梯找拐点

第 1 步:采集 LLM 专属指标

大模型压测不能只看总耗时,要拆成 TTFT(等待体验)、TPOT(出字流畅度)、吞吐(系统产能)三组:

import asyncio, time, aiohttp

async def one_request(session, sem, question, out):
    async with sem:
        t0 = time.time(); ttft = None; n = 0
        async with session.post(URL, json={"q": question}) as r:
            async for line in r.content:
                if not line.startswith(b"data:"):
                    continue
                n += 1
                if ttft is None:
                    ttft = time.time() - t0          # 首 token 延迟
        total = time.time() - t0
        out.append({
            "ttft": ttft, "total": total, "tokens": n,
            "tpot": (total - ttft) / max(n - 1, 1),  # 每 token 间隔
        })

async def run_load(concurrency, n_req, questions):
    out, sem = [], asyncio.Semaphore(concurrency)
    async with aiohttp.ClientSession() as s:
        await asyncio.gather(*[
            one_request(s, sem, questions[i % len(questions)], out)
            for i in range(n_req)])
    return summarize(out)   # P50/P95/P99 + 超时率 + 吞吐(tokens/s)

第 2 步:阶梯加压,找拐点定水位

def capacity_test():
    curve = []
    for c in (1, 5, 10, 20, 40):                 # 阶梯并发
        m = run_until_stable(c)
        curve.append((c, m["ttft_p95"], m["tpot_p95"], m["timeout_rate"]))
    knee = find_knee(curve)                       # TTFT 开始非线性上涨的点
    assert PROD_CONCURRENCY <= knee * 0.7, \
        f"生产水位 {PROD_CONCURRENCY} 超过拐点 {knee} 的 70%,容量不足"

事故服务的拐点在并发 12 左右,而大促实际并发峰值 60——五倍于拐点,不卡才怪。修复动作:限流到拐点 70%、超限请求进排队页、备用小模型兜底短问答,压测报告里这三条都要有对应演练用例。

三、沉淀成方法:LLM 压测指标体系

维度 传统接口 大模型服务 阈值参考
等待体验 RT TTFT P95 对话类 < 3s
流畅度 TPOT P95 < 100ms/字
产能 QPS 吞吐 tokens/s、并发拐点 阶梯压测找
稳定性 错误率 超时率、排队深度、504 率 < 0.1%

三条工程纪律:一是压测流量要混长短文本——全用短问题压出来的容量是假的,长上下文请求吃 KV cache 的速度是短请求的几十倍,用例集要按线上真实长度分布配比;二是压测环境必须含网关和排队层,只压模型裸服务会漏掉网关超时、队列积压这些真实瓶颈;三是每次模型/推理框架升级重跑容量曲线,换个模型版本拐点可能移动 30%,容量结论是有"保质期"的。

四、面试追问,你答得上来吗

  1. 大模型压测和传统压测的本质区别?——答:传统接口响应是"一次性、字节数小、耗时稳定",大模型响应是"流式、耗时随输入输出长度剧烈变化、GPU 资源有状态(KV cache)“。所以指标从 QPS/RT 换成 TTFT/TPOT/吞吐,容量从"扛多少 QPS"换成"拐点并发是多少”,而且同样的并发下长短文本表现完全不同,必须按真实分布压。
  2. 怎么定容量水位和扩容线?——答:阶梯压测找拐点(TTFT P95 开始非线性上涨的并发数),生产水位压在拐点 70% 以下;告警线设在拐点 50%,给扩容和限流留反应时间。水位不是越高越好——越过拐点后吞吐不升反降,压得越狠死得越快。
  3. TTFT 正常但 TPOT 恶化,说明什么?——答:说明首 token 前的排队和预填充还扛得住,但解码阶段资源吃紧——典型是 KV cache 不足导致批处理抢占、或显存带宽打满。反过来 TTFT 高 TPOT 正常,则是排队/预填充瓶颈。两个指标分开看,才能定位到推理管线的哪一段。

下一篇预告:《聊着聊着就报错了——上下文溢出与 Token 边界测试》

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。