1. 概述

为什么LLM推理性能测试至关重要

在我处产品测试工作中,随着大语言模型在智能客服、代码辅助、文档分析等业务场景的深度集成,LLM推理性能直接影响用户体验和系统可用性。与传统Web应用不同,LLM推理具有流式输出、Token级延迟、显存密集型等独特特征,传统的QPS/响应时间指标体系已不足以全面评估其性能表现。

以金融行业典型场景为例:一个智能投研助手需要实时分析多份财报并生成摘要,如果首Token延迟超过2秒,分析师的使用意愿将急剧下降;如果并发处理能力不足,高峰时段的服务质量将无法保障。因此,建立科学的LLM推理性能测试体系是我处AI质量保障的核心任务之一。

LLM推理性能测试 vs 传统Web应用性能测试

对比维度传统Web应用LLM推理
核心指标QPS、平均响应时间、错误率TTFT、TPOT、tokens/s、端到端延迟
响应模式一次性返回完整结果流式逐Token生成(SSE)
资源瓶颈CPU、内存、网络I/OGPU显存、显存带宽、计算单元利用率
负载特征请求独立、无状态请求具有KV Cache状态、显存驻留
延迟构成网络+业务处理+数据库Prompt编码 + Token生成(自回归)
压测工具JMeter、Locust、GatlingJMeter + SSE插件、vLLM benchmark、自研脚本
容量评估基于QPS的线性扩展基于GPU显存和并发数的非线性扩展
💡 我处实践经验 在多轮LLM性能测试中,我们发现:即使是同一模型、同一硬件配置,输入Prompt的长度差异(如100 tokens vs 4000 tokens)可导致首Token延迟相差3-5倍。因此,性能测试必须覆盖短/中/长文本多种输入场景,这与传统接口测试中用固定入参压测的思路有本质区别。

2. 核心性能指标

LLM推理性能评估需要从用户感知延迟系统吞吐效率两个维度综合考量。以下是我处性能测试中重点关注的五大核心指标:

指标英文缩写定义业务阈值参考测量方法
首Token延迟 TTFT 从发送请求到收到第一个Token的时间间隔,包含Prompt编码和首个Token生成 < 500ms(实时对话)
< 2s(文档分析)
记录SSE流中首个data事件的时间戳
每Token延迟 TPOT 后续每个Token生成的平均间隔时间(不含首Token) < 50ms(保证流畅感) (末Token时间 - 首Token时间)/(总Token数 - 1)
吞吐量 Throughput 单位时间内系统处理的Token总量(包括输入和输出) 根据硬件和模型差异评估 总Token数 / 总耗时(含并发叠加)
并发能力 Concurrency 系统在满足SLO前提下能同时处理的请求数 不低于预估峰值的1.5倍 逐步增加并发数直至TTFT/SLO超标
端到端响应时间 E2E Latency 用户从发起请求到接收完整响应的总时间 < 10s(常规问答) TTFT + TPOT × 输出Token数
⚠️ 关键提醒 TTFT和TPOT需要分开测量,不可混为一谈。在实际压测中,TTFT受输入长度影响最大(Prompt越长编码越慢),TPOT则主要受模型参数量和显存带宽制约。我处曾遇到过一个案例:某模型TPOT表现极佳(<20ms),但TTFT在长Prompt场景下高达3秒,导致用户体验仍然很差——因为用户盯着空白界面等了3秒才开始看到输出。

3. 测试方法

3.1 流式响应测试(SSE)

LLM推理的主流交互方式是基于Server-Sent Events(SSE)的流式输出。测试时需要精确捕获和记录每个Token到达的时间戳,这比传统HTTP请求-响应模式的测试更复杂。在我处测试实践中,我们基于JMeter开发了专门的SSE流式响应采样器,能够:

// SSE流式响应解析核心逻辑(JMeter JSR223 采样器示例)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;

def conn = new URL("${endpoint}/v1/chat/completions").openConnection()
conn.setRequestMethod("POST")
conn.setRequestProperty("Authorization", "Bearer ${apiKey}")
conn.setRequestProperty("Content-Type", "application/json")
conn.setDoOutput(true)

// 写入请求体
def body = '''
{
  "model": "${model}",
  "messages": [{"role": "user", "content": "${prompt}"}],
  "stream": true,
  "max_tokens": 2048
}'''
conn.outputStream.write(body.getBytes("UTF-8"))

// 读取SSE流并记录时间
def reader = new BufferedReader(new InputStreamReader(conn.inputStream))
long startTime = System.currentTimeMillis()
long firstTokenTime = 0
int tokenCount = 0
String line

while ((line = reader.readLine()) != null) {
    if (line.startsWith("data: ")) {
        def data = line.substring(6)
        if (data == "[DONE]") break
        if (firstTokenTime == 0) {
            firstTokenTime = System.currentTimeMillis()
        }
        tokenCount++
    }
}

long endTime = System.currentTimeMillis()
long ttft = firstTokenTime > 0 ? firstTokenTime - startTime : -1
double tpot = tokenCount > 1 ? (endTime - firstTokenTime) / (tokenCount - 1) : 0

// 写入JMeter变量
vars.put("ttft_ms", String.valueOf(ttft))
vars.put("tpot_ms", String.valueOf(Math.round(tpot)))
vars.put("total_tokens", String.valueOf(tokenCount))
vars.put("e2e_ms", String.valueOf(endTime - startTime))

log.info("TTFT=${ttft}ms, TPOT=${Math.round(tpot)}ms, Tokens=${tokenCount}")

3.2 批量推理测试

批量推理(Batch Inference)适用于离线场景,如批量文档摘要、数据标注等。测试要点包括:

3.3 并发压力测试

模拟多用户同时访问的场景,评估系统在并发压力下的性能退化曲线。在我处实践中,采用阶梯式加压策略:

  1. 从1并发开始,每30秒增加5个并发线程
  2. 持续监控TTFT P50/P95/P99的变化趋势
  3. 当P95 TTFT超过SLO阈值时,记录此时的并发数为系统容量上限
  4. 继续加压至服务极限,观察队列机制是否正常工作

3.4 持续负载测试

长时间保持一定并发量运行(通常≥2小时),检验系统在持续负载下的稳定性。重点关注:

4. 影响因素分析

LLM推理性能受多种因素的综合影响,测试时需要系统性地进行变量控制和对比分析:

影响因素影响维度典型规律测试建议
模型大小 TPOT、显存占用 7B→70B,TPOT约增加3-5倍,显存用量约增加8-10倍 建立不同模型大小的性能基线,辅助模型选型决策
量化精度 吞吐量、显存占用、精度损失 FP16→INT8吞吐提升~2x,显存减半;INT4吞吐再提升~1.5x,但精度损失需评估 对每种量化精度独立测试,关联精度评测结果
输入长度 TTFT、显存占用 输入Token数翻倍,TTFT约增加40%-80% 按短/中/长文本设计测试用例组(如256/1024/4096 tokens)
输出长度 端到端延迟、TPOT 输出Token数超KV Cache窗口时TPOT骤升 设置不同max_tokens参数进行对比测试
GPU配置 整体性能 H800相较A100,推理吞吐提升~2-3x(同精度下) 记录硬件配置详情,作为性能报告必备附件
推理引擎 并发能力、吞吐量 vLLM的Continuous Batching显著优于静态批处理;TensorRT-LLM在特定硬件上有额外优化 在同等条件下对比不同引擎的性能表现
📖 我处实践总结 在近期一次模型选型评测中,我们对比了量化精度(FP16 vs INT8 vs INT4)对金融知识问答系统性能的影响。测试发现:INT8量化在性能提升(~2x吞吐)和精度损失(<1% BLEU下降)之间取得了最佳平衡,目前已成为我处推荐的默认部署方案。详细的对比数据和测试脚本可参见性能测试报告库。

5. 测试工具

5.1 JMeter + 自建SSE插件

我处性能测试团队在Apache JMeter基础上进行了深度定制,开发了适配LLM推理测试的专用组件:

# JMeter非GUI模式命令行执行示例
# 适用于CI/CD流水线集成

jmeter -n -t llm_perf_test.jmx \
  -Jendpoint=http://gpu-server:8000 \
  -Jmodel=qwen2-72b-int8 \
  -Jconcurrency=10 \
  -Jduration=300 \
  -Jprompt_file=prompts_dataset.csv \
  -l results/llm_perf_$(date +%Y%m%d_%H%M%S).jtl \
  -e -o reports/llm_perf_$(date +%Y%m%d_%H%M%S)/

5.2 vLLM性能基准工具

vLLM官方提供的benchmark_serving.py是业界广泛使用的LLM推理基准测试工具。其优势在于:

# vLLM benchmark 典型命令
python -m vllm.entrypoints.openai.api_server \
  --model /models/qwen2-72b-int8 \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.9

# 在另一个终端执行基准测试
python benchmarks/benchmark_serving.py \
  --backend vllm \
  --model qwen2-72b-int8 \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 512 \
  --request-rate 8 \
  --num-prompts 500 \
  --result-dir ./benchmark_results/

5.3 OpenAI API兼容测试

大多数LLM推理框架(vLLM、TGI、Ollama等)均提供OpenAI兼容的API端点。这使我们可以用统一的接口进行跨引擎对比测试。我处封装了一套轻量级的Python测试脚本,支持:

6. 实战演练

💡 演练说明 以下任务基于我处实际测试环境和经验设计,涵盖LLM推理性能测试的典型工作流程。建议按照顺序完成,从基础工具使用逐步过渡到综合对比分析。

任务1:使用JMeter对LLM推理服务进行延迟基准测试

目标:掌握JMeter SSE采样器的配置和使用方法,建立LLM推理性能测试基线。

环境要求:

步骤要点:

  1. 创建JMeter测试计划,添加Thread Group(线程数=1,循环=10)
  2. 配置SSE采样器:填入API endpoint、model名称、stream=true
  3. 通过CSV Data Set Config读取测试Prompt数据集
  4. 添加JSR223后置处理器,解析SSE流并计算TTFT/TPOT
  5. 添加Aggregate Report和Summary Report监听器
  6. 执行测试,记录三类文本长度的TTFT/TPOT基线数据

预期产出:一份包含P50/P95/P99统计的延迟基线报告,作为后续性能调优的对比基准。

任务2:对比不同量化精度下的推理性能

目标:量化评估FP16、INT8、INT4三种精度在推理吞吐、延迟和显存消耗上的差异,为部署选型提供数据支撑。

测试矩阵:

模型量化精度并发数输入长度输出长度关注指标
Qwen2-72BFP161 / 4 / 81024512基线参考
Qwen2-72BINT81 / 4 / 81024512吞吐提升倍数
Qwen2-72BINT41 / 4 / 81024512极限吞吐+精度损失

关键操作:

  1. 分别部署FP16/INT8/INT4版本的推理服务,确保其他配置一致
  2. 使用JMeter或vLLM benchmark工具执行相同测试用例
  3. 同步采集GPU利用率(nvidia-smi dmon)和显存占用数据
  4. 绘制「并发数 vs 吞吐量」和「并发数 vs P95 TTFT」双维度对比图
  5. 关联精度评测数据,计算「性能提升 / 精度损失」的ROI比值

任务3:并发压力测试——探寻系统容量上限

目标:通过阶梯式加压找到当前部署方案的最大并发承载能力,验证排队和限流机制的有效性。

压测方案:

分析维度:

  1. 容量拐点识别:找到TTFT开始急剧恶化的并发数阈值
  2. 排队行为验证:当请求数超过处理能力时,服务端是否正确返回429或排队等待
  3. 资源瓶颈定位:通过GPU监控数据判断瓶颈是显存容量、显存带宽还是计算单元
  4. 恢复能力测试:在压力达到峰值后迅速降载,观察性能是否能在1分钟内回归基线
🔴 安全警示 在生产环境进行压力测试前,务必确认:(1) 已与运维团队沟通并获得授权;(2) 测试流量已做好标识,可与真实流量区分;(3) 已准备应急回滚方案。严禁在无保护措施的情况下对生产服务进行破坏性压测。

📋 案例研究:银行智能客服的LLM推理性能测试

背景:某大型商业银行计划将智能客服系统升级为基于大语言模型的方案,需支持500并发用户,端到端响应时间 < 3秒。在正式上线前,需要进行全面的推理性能测试以验证系统能力。

测试过程

  • 使用 JMeter 对LLM API进行阶梯式并发测试(Stepped Ramp-Up)
  • 并发从 50 逐步增加到 500,每阶梯持续5分钟
  • 监控指标:TTFT(首Token时间)、TPOT(每Token时间)、端到端延迟错误率
  • 对比了 7B70B 两种参数规模模型的性能差异
  • 测试环境:4×A100-80GB GPU,vLLM推理框架,FP16精度

测试结果

并发数 7B TTFT (ms) 7B TPOT (ms) 7B E2E (s) 70B TTFT (ms) 70B TPOT (ms) 70B E2E (s) 错误率
50 180 22 0.82 420 35 1.45 0.00%
100 215 26 1.05 560 42 1.92 0.00%
200 310 32 1.58 1040 55 2.76 0.02%
300 520 45 2.35 1820 78 4.12 0.15%
400 780 58 3.20 2850 110 6.80 0.48%
500 1100 75 4.50 3.20%

关键发现:

  • 🟡 300并发时系统达到性能拐点,7B模型的TTFT从310ms(200并发)急剧攀升至520ms
  • 🔴 70B模型在200并发时TTFT已超过1秒阈值(1040ms),不适合高并发场景
  • 🟢 7B模型可支撑500并发,但TTFT达到1.1s且E2E超4.5s,超出3s目标
  • ❌ 70B模型在500并发时3.2%错误率,基本不可用(表中标记"—")
💡 核心启示
  1. 找拐点比测极值更重要:性能测试的目标不是简单测出"最大并发数",而是找到TTFT突然恶化的拐点(本例为300并发),这才是系统的实际可用容量上限。
  2. 模型大小与并发能力需权衡:70B模型回答质量更优,但并发能力远弱于7B。在延迟敏感的场景下,小模型往往是更务实的选择。
  3. 混合部署策略:建议采用两级路由——简单高频问题(余额查询、密码重置等)由7B小模型处理,复杂长尾问题由70B大模型异步处理,兼顾性能与质量。