用 bench_one_batch.py 做最小执行显微镜#

这章解决什么问题#

代码导读前面已经给出了从 README、HTTP surface、Engine API、protocol.pyio_struct.pyscheduler.py 的多条阅读路径,但还差一种非常高效的“缩小版执行入口”:如果你不想先启动整个 server,也不想一上来就读完整 runtime 主线,有没有一个更小、更可控的文件能帮你直接看到“准备输入 -> 构造 batch -> forward -> sample -> 计时/profile”的最小闭环?

python/sglang/bench_one_batch.py 正是这样一个入口。

为什么这个文件特别适合拿来当“显微镜”#

它的文件头就把目标说得很清楚:Benchmark the latency of running a single static batch without a server. 这句话非常关键,因为它意味着这个脚本故意绕开了完整 server path,专门留下低层执行路径。

这让它特别适合做两件事:

  • 作为理解执行模型的缩小版入口
  • 作为性能/正确性实验时的最小复现入口

一本更厚的技术书不应该只让读者在大系统里游泳,也应该给他几个“可以单步观察”的浅水区。bench_one_batch.py 就是其中之一。

一张图:这个脚本把完整系统压成了哪条最小链路#

这张图解决的理解障碍是:很多读者会把 benchmark 脚本想成“只是跑一下性能”,而忽略它实际上已经保留了执行闭环中最核心的几步。

flowchart LR
    Input["prepare prompts / ids"] --> Req["Req / ScheduleBatch"]
    Req --> Fwd["ForwardBatch / ModelRunner.forward()"]
    Fwd --> Sample["model_runner.sample()"]
    Sample --> Measure["latency / profile / correctness output"]

这张图比纯文字多解释的一点是:这个脚本不是在跑“另一套逻辑”,而是在把完整 runtime 的执行脊梁压缩成更适合观察的一小段。

为什么它比直接读 scheduler.py 更容易进入状态#

因为 scheduler.py 同时背着:

  • 接收请求
  • 排队
  • batch 形成
  • overlap / disaggregation / retract
  • 结果处理

bench_one_batch.py 则有意把这些复杂度剥掉,只留下最靠近执行的部分。所以对于第一次真正想搞懂 ForwardBatch -> forward -> sample 的读者,这个脚本往往比直接读核心调度循环更容易上手。

这个脚本最值得盯住的几段#

prepare_inputs_for_correctness_test(...)#

它把输入准备显式化。对读者来说,这很重要,因为它把“请求一开始长什么样”降到了最可观察形式,而不是让你从 HTTP payload 或复杂 prompt builder 入手。

ModelRunner.forward(...) 之后立刻 sample(...)#

文件里有直接调用 model_runner.sample(logits_output, forward_batch) 的路径。这特别适合当执行模型章节的最小版回读材料,因为它把“前向之后到底接什么”写得非常直接。

latency_test_run_once(...)#

这是理解性能实验组织方式的最好入口。它告诉你:这个脚本并不只跑 correctness,也会把 latency 测试和 profile 组织成明确的实验步骤。

为什么这个文件对“书感”特别重要#

因为它把整本书前后几章自然串在一起:

  • 执行模型章节会解释 ForwardBatchsample(...)、logits 和输出语义
  • 调度与内存章节会解释为什么真实系统里 batch 没这么简单
  • profiling 章节会解释为什么这类最小实验入口对性能分析很有价值

换句话说,这个文件非常适合充当“从书本原理回到最小可运行实验”的桥。

这个脚本不在讲什么#

这也很重要。它不打算解释:

  • HTTP / OpenAI surface
  • 完整 manager 主链
  • 多 worker 路由
  • 完整 waiting queue / priority / routing-key 重排

这不是缺点,而是它作为“显微镜入口”最有价值的地方:它就是故意缩小作用域。

更稳的阅读顺序#

建议这样读:

  1. 先带着执行模型章节里的心智模型来读
  2. 只盯输入准备、Req/ScheduleBatchForwardBatchforwardsample
  3. 再看 correctness 和 latency/profile 两类模式如何分开组织
  4. 最后再回到 scheduler.py 对照:真实系统相比这个显微镜入口,多出来了哪些复杂度

这一层最容易出现的误判#

1. 把它当成“纯 benchmark 脚本”#

它其实也是非常好的执行链阅读入口。

2. 把它当成和真实 runtime 无关的 toy#

它用的正是低层 runtime API,只是刻意剥掉了外围复杂度。

3. 以为在这里看不见 request object / batch object#

实际上它恰好把这些对象压缩到了更易观察的范围里。

如果你想用它帮助自己理解系统,先怎么走#

建议按这个顺序:

  1. 先看文件头 usage,确认它支持 correctness / latency / profile 三类用途。
  2. 再看 prepare_inputs_for_correctness_test(...)
  3. 再看 latency_test_run_once(...)
  4. 最后只盯 ModelRunner.forward(...)sample(...)

小结#

这一章真正想补齐的,是代码导读里非常缺的一类入口:

  • 不是完整系统入口
  • 不是纯文档入口
  • 而是“足够接近真实执行、又足够小”的显微镜入口

到这里,代码导读部分就不只是告诉你“哪些目录重要”,也开始提供“如何用最小实验脚本理解整条执行链”的方法。