DeepInfer 压测吞吐对不上预期——批处理和超时哪一项在拖后腿

文章导读
压测吞吐低于预期时,先把问题拆成三个可以分别观察的来源:发压客户端能不能打满、服务端批处理是否真的生效、超时和排队是否在压测期间丢弃了一部分请求。比较稳妥的做法是固定模型、固定输入输出长度和固定采样参数,只改一个变量做对照压测;每轮都记录客户端并发、连接复用情况、服务端日志里的实际批大小与超时错误数量。只看总吞吐数字,通常无法区分是批处理没配好,还是请求在超时后被丢弃,或者发压端根本没有发出足够的
📋 目录
  1. 壹 先确认压测客户端本身不是瓶颈
  2. 贰 记录服务端批处理配置与日志里的实际批次
  3. 叁 固定输入输出长度重跑一轮压测
  4. 肆 检查超时与排队是否在悄悄丢请求
  5. 伍 用两组对照数据给出归因结论
A A

压测吞吐低于预期时,先把问题拆成三个可以分别观察的来源:发压客户端能不能打满、服务端批处理是否真的生效、超时和排队是否在压测期间丢弃了一部分请求。比较稳妥的做法是固定模型、固定输入输出长度和固定采样参数,只改一个变量做对照压测;每轮都记录客户端并发、连接复用情况、服务端日志里的实际批大小与超时错误数量。只看总吞吐数字,通常无法区分是批处理没配好,还是请求在超时后被丢弃,或者发压端根本没有发出足够的请求。

当 DeepInfer 的压测吞吐明显低于预期时,建议按四步顺序做对照压测:先排除压测客户端自身的连接与并发限制,再从服务端日志确认实际批大小,然后用固定输入输出长度重跑一轮,最后统计超时和被拒请求。判定规则很简单:客户端并发拉高而服务端并发没有随之上升,瓶颈就在客户端;服务端日志的批大小长期为 1,说明批处理未生效;日志中出现超时或排队丢弃,说明吞吐被丢弃的请求占用了。每次只改一项配置,用同一组指标前后对照,不要一次调整多个参数。

先确认压测客户端本身不是瓶颈

发压工具常见的限制在于并发连接数、HTTP 连接池大小和请求超时设置,与模型服务大多无关。如果客户端只开几个连接,或者每次请求都新建连接,那么服务端看到的并发就上不去,吞吐自然会显得偏低。可以先检查客户端一侧的这几个配置项:并发协程或线程数、连接池上限、keep-alive 是否开启、单请求超时是否短于服务端实际响应时间。

观察方式建议同时看两边:一边看压测客户端自己记录的实际并发数和错误数,另一边看服务端日志或监控里的在途请求数。如果客户端显示并发已经拉到目标值,但服务端在途请求数明显更低,那么请求可能堆积在连接建立或排队阶段;如果服务端在途请求数也上不去,就先怀疑客户端没有真正发出这些请求。

# 通用发压骨架,参数按实际工具替换
# 关键:并发数、连接复用、超时都要显式设置
bench_client \
  `--target` http://127.0.0.1:8000/generate \
  `--concurrency` 32 \
  `--connections` 32 \
  `--keep-alive` true \
  `--request-timeout` 60s \
  `--duration` 120s \
  `--payload` fixed_payload.json \
  `--report-json` client_report.json

运行后先看 client_report.json 里的成功数、失败数、平均延迟和实际并发,再与服务端日志对照。若客户端失败数不为零,先解决客户端错误,再谈服务端吞吐。

记录服务端批处理配置与日志里的实际批次

批处理配置生效与否,不能只看配置文件写了多少,要结合日志里每批实际处理的请求数量来判断。通常需要确认这几类配置项:批处理开关、最大批大小(max batch size)、批等待时间(batch timeout 或 max wait)、并发执行的批数量。批等待时间设置过大时,请求会等更久才凑成一批,吞吐可能上不去、延迟反而变高;批大小上限设置过小时,即使有请求排队也无法合批。

日志里应重点找每批的实际条数、批等待耗时、排队长度的记录。如果日志中每批条数长期是 1,或者批等待时间经常顶到上限,说明批处理没有按预期聚合;如果根本找不到批次相关日志,可以先确认日志级别是否够细,或在配置里打开批处理维度的统计输出。

# 通用检查思路,字段名以实际日志为准
grep -iE "batch|queue|wait" deepinfer-server.log | tail -n 200

# 关注三类行:
# 1) 每批多少条请求
# 2) 本批等待了多久才凑齐
# 3) 队列长度是否持续增长

这一步的边界是:日志只能说明服务端实际做了几批,不能直接说明瓶颈在批处理。要结合固定长度重跑和超时统计才能归因。

DeepInfer 压测吞吐对不上预期——批处理和超时哪一项在拖后腿

固定输入输出长度重跑一轮压测

前后两轮压测如果输入长度不同,吞吐对比基本没有意义,因为长输入会拉长单批处理时间,也会改变批处理能否凑满。固定变量的做法是:同一模型、同一采样参数(如 max tokens)、同一批固定输入样本,尽量让每轮使用的输入 token 数与输出 token 数保持一致,再分别跑两轮只改一个服务端配置的压测。

# 建议每轮压测都记录这些指标
# - 客户端:成功数、失败数、平均延迟、P95 延迟、实际并发
# - 服务端:每批平均条数、批等待时间、队列长度、超时或拒绝次数
# - 输入输出:输入 token 数、max tokens 设置

# 运行顺序建议
# 第 1 轮:当前配置,作为基线
# 第 2 轮:只改批大小或批等待时间中的一项,其他不变

每轮结束后把指标写进表格,不要凭印象判断。固定变量做到了,后面两轮的差异才能归因到被改的那一项。

检查超时与排队是否在悄悄丢请求

吞吐偏低有时并不表示服务端处理能力不足:一部分请求可能在超时后被丢弃,或者因为没有通过排队而被拒绝,并未进入计算,但客户端仍然把这些请求计入“已发送”。日志中典型的表现是超时错误、请求被拒绝、队列满丢弃、连接被重置这几类记录。建议按错误类型分别统计数量,而不是只统计一个总数。

# 统计被拒或超时的请求数量,字段名以实际日志为准
grep -iE "timeout|timed out|reject|queue full|dropped" deepinfer-server.log \
  | awk '{print $NF}' | sort | uniq -c | sort -nr | head

同时对照客户端的失败数和超时数:如果两边数量接近,说明这部分请求确实没有完成处理,吞吐自然偏低。处理方向是先判断是客户端超时设得太短,还是服务端批等待把延迟拉长到了超时线以上。这一步需结合环境确认,不能直接按日志里的错误数量推断服务端处理能力。

用两组对照数据给出归因结论

把前四步的结果整理成一张对照表,是判断“批处理和超时哪一项在拖后腿”的可操作方式。表格不需要复杂,但要能看出每轮只改了什么、客户端与服务端指标如何变化。

| 轮次 | 改动项 | 客户端实际并发 | 成功/失败数 | 服务端每批平均条数 | 超时或拒绝数 | 备注 |
|------|--------|----------------|-------------|--------------------|--------------|------|
| 基线 | 无     |                |             |                    |              |      |
| 第2轮 | 批大小/批等待时间只改一项 | |       |                    |              |      |
| 第3轮 | 客户端并发或连接池只改一项 | |      |                    |              |      |

判定规则可以按下面的顺序使用:客户端实际并发上不去、服务端在途请求也不高,先修发压客户端的并发和连接复用;客户端并发已达标、服务端日志每批平均条数接近 1,先查批处理配置是否生效;批大小正常但超时或拒绝数明显,先查批等待时间与超时线的匹配关系。对应的修改项分别是:客户端并发与连接池配置、服务端批处理开关与批大小、批等待时间、客户端单请求超时。每次只改一项,按同一张表重新记录,直到吞吐变化能被某一项解释为止。