# DSpark TTFT 长于 vLLM baseline 的根因分析

## 数据回顾

| Scenario | Backend | Conc | Input | Output | Mean TTFT(ms) | P95 TTFT(ms) | P99 TTFT(ms) | Mean TPOT(ms) | Req/s |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|
| c1_i512_o256 | vllm-dspark | 1 | 512 | 256 | 86.51 | 185.00 | 188.81 | 2.09 | 2.56 |
| c1_i512_o256 | vllm-default | 1 | 512 | 256 | 49.50 | 68.50 | 71.09 | 6.66 | 0.99 |
| c32_i512_o256 | vllm-dspark | 32 | 512 | 256 | 262.56 | 527.21 | 532.11 | 12.06 | 16.53 |
| c32_i512_o256 | vllm-default | 32 | 512 | 256 | 122.62 | 272.00 | 304.80 | 15.77 | 12.98 |
| c128_i512_o256 | vllm-dspark | 128 | 512 | 256 | 778.36 | 1071.85 | 1075.35 | 28.95 | 23.94 |
| c128_i512_o256 | vllm-default | 128 | 512 | 256 | 617.72 | 767.18 | 770.89 | 18.31 | 29.99 |
| c1_i4000_o512 | vllm-dspark | 1 | 4000 | 512 | 123.58 | 176.29 | 190.52 | 1.66 | 1.73 |
| c1_i4000_o512 | vllm-default | 1 | 4000 | 512 | 131.50 | 191.53 | 268.69 | 6.68 | 0.50 |
| c32_i4000_o512 | vllm-dspark | 32 | 4000 | 512 | 298.42 | 434.24 | 522.34 | 9.68 | 11.49 |
| c32_i4000_o512 | vllm-default | 32 | 4000 | 512 | 382.74 | 681.98 | 684.75 | 16.43 | 5.38 |

## 核心结论

**DSpark 在短输入（i=512）场景下 TTFT 明显长于 vLLM baseline，是投机解码机制本身的正常 trade-off，但在当前配置下 overhead 偏大，有优化空间。**

## 为什么短输入场景 TTFT 会变差？

### 1. 投机解码的本质 overhead

DSpark 在生成第一个 token 时，除了执行一次目标模型（target model）的 prefill，还要：
- 加载并执行 draft model；
- 让 draft model 连续预测最多 `spec-tokens=5` 个 token；
- 用 target model 对这 5 个 token 做并行验证（verification）；
- 根据验证结果回退或接受。

对于 **短输入（512 tokens）**，baseline 的 prefill 本身非常快（P50 仅 44-65ms），draft model 的额外 forward + verification 的固定 overhead 占了 TTFT 的很大比例，导致 TTFT 反而变长。

### 2. 长输入场景反而受益

对于 **长输入（4000 tokens）**，prefill 是主要瓶颈。DSpark 通过 draft model 投机生成后续 token，能显著减少 target model 的 forward 次数，因此：
- c1_i4000_o512：TTFT 与 baseline 接近（123ms vs 131ms），但 TPOT 从 6.68ms 降到 1.66ms；
- c32_i4000_o512：TTFT 明显优于 baseline（298ms vs 383ms，-22%），TPOT 从 16.43ms 降到 9.68ms。

这符合投机解码的设计目标：**用 draft model 的额外计算换取 target model 更少的完整 forward，从而在长序列或高输出长度上获得端到端收益。**

### 3. 高并发短输入场景被放大

在 c128_i512_o256 下：
- DSpark 的 Req/s 低于 baseline（23.94 vs 29.99），说明单位时间内处理的请求更少；
- 同时 DSpark 的 mean TPOT 高于 baseline（28.95ms vs 18.31ms）。

这说明在并发较高、输入较短时，DSpark 的 draft-verification 流水线没有跑赢 baseline 的简单 decode，导致队列等待时间增加，进一步放大了 TTFT。

## 是代码缺陷还是正常现象？

### 属于正常现象的部分

1. **短输入下投机解码增加 TTFT 是预期行为**：只要 draft model 不是零成本，第一个 token 必然比 baseline 慢。
2. **DSpark 的收益主要体现在 TPOT/E2E/吞吐量**：所有场景下 DSpark 的 TPOT 都显著低于 baseline，长输入场景 E2E 也大幅缩短。

### 可能存在优化空间的部分

1. **`spec-tokens=5` 对短输入可能过大**
   - 当前 DSpark 使用 `--spec-tokens 5`。
   - 对于 512 token 的短输入，prefill 后只需要 256 个输出 token，一次 spec 5 个 token 的 verification overhead 相对较高。
   - **建议**：对短输入场景尝试 `spec-tokens=1` 或 `spec-tokens=2`，看是否能降低 TTFT overhead 同时保持 TPOT 收益。

2. **DSpark 与 default 使用不同 checkpoint**
   - DSpark 模型路径是 `/data/models/DeepSeek-V4-Flash-DSpark`，而 baseline 是 `/data/models/DeepSeek-V4-Flash`。
   - 如果 DSpark checkpoint 的 prefill 路径没有被充分优化（例如 MLA/KV cache 格式差异），可能会额外增加 prefill 时间。
   - **建议**：确认两个 checkpoint 在 prefill 阶段是否使用相同的 kernel/量化路径，排除模型差异本身带来的 TTFT 偏移。

3. **draft model 与 target model 的调度/重叠**
   - 如果 draft model 的 forward 和 target model 的 verification 没有充分 overlap，TTFT 会进一步恶化。
   - **建议**：通过 vLLM 的 profile/profiling 工具查看 prefill 阶段 draft model 是否串行执行，以及是否可以通过 `--spec-max-model-len` 或调度参数优化。

4. **高并发下的 batching 策略**
   - c128_i512_o256 下 DSpark 吞吐量低于 baseline，可能是 speculative decoding 在高并发下的 batching 效率下降。
   - **建议**：测试不同 `max-num-seqs` 或 `--max-num-batched-tokens` 配置，观察并发吞吐和 TTFT 的变化。

## 建议的下一步

1. **参数调优实验**：固定模型和硬件，扫描 `spec-tokens ∈ {1, 2, 3, 5}`，重点观察短输入场景的 TTFT 和 TPOT 变化。
2. **profiling**：在 c1_i512_o256 和 c32_i512_o256 下，用 vLLM 的 `--profile` 或 Nsight 抓取 prefill 时间线，确认 draft model 的 overhead 占比。
3. **与 MTP 对比**：当前正在跑的 vLLM+MTP 实验会提供另一组投机解码数据，可以对比 DSpark 和官方 MTP 在 TTFT/TPOT 上的 trade-off 差异。

## 总结

DSpark 在短输入场景 TTFT 变差**不是代码 bug，而是投机解码机制的正常开销**。但当前 `spec-tokens=5` 的配置在短输入下 overhead 偏大，建议通过调参和 profiling 进一步优化，尤其是在 S1 实时交互层（输入短、延迟敏感）场景。
