Skip to content

Benchmark ​

SGLang benchmark 用于比较不同 batch size 或服务并发下的延迟与吞吐。固定 batch 使用 bench_one_batch,HTTP 服务压测使用 bench_serving;kernel 时间线采集见 Profile。

1. 测量口径与环境 ​

目标工具结果
固定 batch 的模型执行成本sglang.bench_one_batchPrefill latency、median decode latency
服务在不同并发下的表现sglang.bench_servingTTFT、TPOT、ITL、端到端吞吐

Batch size 不等于客户端并发数。 --batch-size 32 表示一次固定 32 条序列的模型测试;--max-concurrency 32 限制 HTTP 在途请求数,实际 GPU batch 会随服务器调度变化。

在安装了 SGLang 的 GPU 机器上使用 Bash 执行。每个终端先设置以下变量:

bash
export MODEL_PATH=/path/to/model
export CUDA_VISIBLE_DEVICES=0
export TP_SIZE=1
export INPUT_LEN=1024
export PORT=30000
export GRAPH_BS_FLAG=--cuda-graph-max-bs-decode
mkdir -p results

替换模型路径,按可见 GPU 数量设置 TP。本文按本地 SGLang 95140a7b0c 核对;旧版若只有 --cuda-graph-max-bs,将 GRAPH_BS_FLAG 改成该名称。当前源码保留 sglang.bench_one_batch、sglang.bench_serving 兼容入口,对应新名称为 sglang.benchmark.one_batch、sglang.benchmark.serving。

2. 固定 Batch 测试 ​

2.1 Prefill 与 10 步 Decode ​

先停止占用同组 GPU 的 server。以下命令只加载一次模型,固定输入长度,依次测量多个 batch size:

bash
python3 -m sglang.bench_one_batch \
  --model-path "$MODEL_PATH" \
  --tp-size "$TP_SIZE" \
  --mem-fraction-static 0.7 \
  --batch-size 1 8 32 64 128 \
  --input-len "$INPUT_LEN" \
  --output-len 11 \
  --run-name prefill_decode10 \
  --result-filename results/batch_prefill_decode10.jsonl

--output-len 是总输出 token 数。普通自回归解码中,prefill 生成首 token,随后执行 output_len - 1 次 decode,因此 1 次 prefill + 10 步 decode 对应 --output-len 11。只测试某个 batch 时,将列表改成一个整数,例如 --batch-size 32。

工具先预热,再分别输出每组的 prefill 和 decode 指标:

字段含义
prefill_latency一次 prefill 的耗时,单位为秒。
prefill_throughput输入 token 吞吐,约为 BS × INPUT_LEN / prefill_latency。
median_decode_latencyDecode 单步耗时的中位数,单位为秒,不包含 prefill 时间。
median_decode_throughputDecode 吞吐,约为 BS / median_decode_latency,单位为 token/s。

10 步适合日常检查和与 profile 对照;稳定性能比较可增加到 --output-len 129,测量 128 步 decode,并重复运行。上下文随 decode 增长,比较不同 batch 时应固定输入、输出长度。同步计时仍包含部分 CPU 发射开销,不等同于所有 GPU kernel 时间之和。

2.2 Prefill 单独测试 ​

只测 prefill 时,将输出长度设为 1:

bash
python3 -m sglang.bench_one_batch \
  --model-path "$MODEL_PATH" \
  --tp-size "$TP_SIZE" \
  --mem-fraction-static 0.7 \
  --batch-size 1 8 32 64 128 \
  --input-len "$INPUT_LEN" \
  --output-len 1 \
  --run-name prefill_only \
  --result-filename results/batch_prefill.jsonl

单独分析 decode 指标时直接读取第 2.1 节的 median_decode_latency,保留前面的真实 prefill 来建立 KV Cache,无需构造虚假缓存。

3. Server 并发测试 ​

3.1 服务启动 ​

终端 A 启动服务,等待 ready。测量正式性能时不加 nsys:

bash
python3 -m sglang.launch_server \
  --model-path "$MODEL_PATH" \
  --host 0.0.0.0 --port "$PORT" \
  --tp-size "$TP_SIZE" \
  --chunked-prefill-size -1 \
  --disable-radix-cache \
  --max-running-requests 128 \
  "$GRAPH_BS_FLAG" 128 \
  --mem-fraction-static 0.7

这是一组便于分析的受控配置:

参数作用
--chunked-prefill-size -1关闭分块 prefill,便于观察完整 prefill;长输入可能增大临时显存需求,并拉长 decode 等待时间。
--disable-radix-cache关闭前缀缓存复用,避免重复输入减少 prefill 计算;decode 的 KV Cache 仍正常使用。
--max-running-requests 128设置运行请求数上限,不会自动产生 128 并发。
"$GRAPH_BS_FLAG" 128设置 decode CUDA Graph 的最大捕获 batch size,不会固定实际 batch size。
--mem-fraction-static 0.7设置模型权重与 KV Cache 池的静态显存预算比例;不是进程总显存占用的硬上限。

评估线上配置时,应恢复线上实际使用的 chunked prefill、前缀缓存和显存预算。不同配置的结果不能直接混为一组。

3.2 Prefill 并发扫描 ​

终端 B 执行以下命令,依次测量 1、8、32、64、128 并发。每个请求只生成 1 个 token,主要观察 TTFT 和输入 token 吞吐:

bash
for C in 1 8 32 64 128; do
  python3 -m sglang.bench_serving \
    --backend sglang \
    --host 127.0.0.1 --port "$PORT" \
    --model "$MODEL_PATH" \
    --dataset-name random \
    --random-input-len "$INPUT_LEN" \
    --random-output-len 1 \
    --random-range-ratio 1 \
    --request-rate inf \
    --max-concurrency "$C" \
    --num-prompts "$((C * 10))" \
    --output-file "results/server_prefill_c${C}.jsonl"
done

--request-rate inf 表示尽快发请求,并由 --max-concurrency 限制在途数量;请求完成后继续补充,直到达到 --num-prompts。--random-range-ratio 1 固定随机数据集的目标输入、输出长度;实际 token 数以测试报告为准。

输出 1 token 已包含 prefill 后的首 token 生成,但不会继续执行常规 decode 循环。TTFT 仍包含 HTTP、排队、调度和输出处理,因此它是 server prefill 场景的端到端指标,不是纯 GPU prefill 时间。此时 TPOT 没有比较意义。

3.3 Decode 并发扫描 ​

保持输入长度不变,生成 128 个 token,主要观察 TPOT、ITL 和输出 token 吞吐:

bash
for C in 1 8 32 64 128; do
  python3 -m sglang.bench_serving \
    --backend sglang \
    --host 127.0.0.1 --port "$PORT" \
    --model "$MODEL_PATH" \
    --dataset-name random \
    --random-input-len "$INPUT_LEN" \
    --random-output-len 128 \
    --random-range-ratio 1 \
    --request-rate inf \
    --max-concurrency "$C" \
    --num-prompts "$((C * 10))" \
    --output-file "results/server_decode_c${C}.jsonl"
done

TPOT 是首 token 之后的平均每 token 时间;ITL 是流式输出的相邻 token 间隔。该测试仍然执行 prefill,而且新请求的 prefill 可能影响正在进行的 decode。输出吞吐也按整个测试窗口统计,不能当成纯 decode kernel 吞吐。

客户端默认先执行预热,并默认忽略 EOS 以满足指定输出长度。示例请求量适合初步扫描;正式比较应增加请求数、重复运行,并保持模型、TP、上下文长度及服务参数一致。输出文件会追加结果,独立实验应使用新文件名。

4. 容量与结果检查 ​

  • 输入长度加输出长度必须符合模型上下文限制;batch 越大、序列越长,KV Cache 需求越高。先跑通小 batch,再增加到 128。
  • bench_one_batch 可能跳过超出容量的配置,应确认每档 batch 都有结果,不能将缺失结果当成测试成功。
  • JSONL 结果按运行追加;独立实验使用新文件名。比较时记录模型、GPU、TP、长度、并发及 CUDA Graph 配置。
  • 本地版本的 random 数据集从 ShareGPT 采样并调整长度,首次使用可能下载数据;离线环境可在 bench_serving 中加 --dataset-path /path/to/sharegpt.json。
  • 正式延迟和吞吐使用不带 profiler 的测试结果。时间线定位方法见 Profile。

5. 参考 ​

  1. SGLang:One Batch Benchmark
  2. SGLang:Server Benchmark