Prhub

#25627 Carve out SchedulerLoadInquirer for queue-load state

原始 PR 作者 fzyzcjy 合并时间 2026-05-18 18:40 文件变更 4 提交数 1 评论 1 代码增减 +125 / -36

执行摘要

创建 SchedulerLoadInquirer 组件并重构队列负载查询方法

此 PR 是调度器组件化重构(Refactor chain ID: introduce-load-inquirer-prep)的一部分,旨在为将队列负载查询逻辑从庞大的 SchedulerMetricsMixin 中完整迁移到独立组件做准备,减少 Mixin 的职责,提高代码可维护性。PR body 明确说明这是 'Inplace prep for the introduce-load-inquirer mech move'。

值得精读,展示了在大型类中安全提取组件的典型做法:先创建轻量容器类(dataclass + callable injection),原地修改方法签名,保证可逆性。可与同一重构链的 PR #25628、#25629 等结合理解完整迁移过程。

讨论亮点

未发现 review 评论记录。作者在 PR body 中明确解释了设计决策:采用 Callable injection 而非 per-call kwarg 是为了保持 get_loads/_get_num_pending_tokens 签名稳定,使后续 'move' 提交成为真正的字节级剪切粘贴,该模式与 SchedulerMetricsReporter 一致。

实现拆解

  1. 创建 SchedulerLoadInquirer 数据类scheduler_components/load_inquirer.py):定义 @dataclass,包含所有必要的依赖字段以及一系列 Callable getter(如 get_waiting_queueget_chunked_req),用于间接访问调度器的运行时可变状态。
  2. Scheduler.__init__ 中实例化scheduler.py):在初始化 pool_stats_observer 之后创建 self.load_inquirer,通过 lambda 捕获当前调度器的属性引用,注入所有 getter。
  3. 重构 SchedulerMetricsMixin 中的两个方法scheduler_metrics_mixin.py):将 get_loads_get_num_pending_tokens 改为 @staticmethod,第一个参数类型从 Scheduler 改为 SchedulerLoadInquirer,所有对 self.waiting_queueself.chunked_req 等直接属性访问替换为对传入 self.get_xxx() getter 的调用。
  4. 更新所有调用点:在 scheduler.py 的 RPC 分派元组(init_request_dispatcher)和 _get_new_batch_prefill_raw 中通过 self.load_inquirer 传递新参数;在 scheduler_output_processor_mixin.pystream_output_generation 中同样调整调用方式。方法体物理移动留待后续 introduce-load-inquirer-move 提交。
文件 模块 状态 重要度
python/sglang/srt/observability/scheduler_metrics_mixin.py 观察层 modified 8.09
python/sglang/srt/managers/scheduler_components/load_inquirer.py 调度器 added 7.82
python/sglang/srt/managers/scheduler.py 调度器 modified 6.76
python/sglang/srt/managers/scheduler_output_processor_mixin.py 输出处理 modified 5.57

关键符号

SchedulerLoadInquirer _get_num_pending_tokens get_loads

关键源码片段

python/sglang/srt/managers/scheduler_components/load_inquirer.py core-logic

新文件:定义 `SchedulerLoadInquirer` 数据类,集中声明所有依赖和 Callable getter 字段,是后续迁移的目标容器。

@dataclass(kw_only=True, slots=True, frozen=True)
class SchedulerLoadInquirer:
    """调度器负载查询器,封装队列负载相关的状态和策略。"""
​
    # 依赖注入:使用 Callable 获取运行时可变状态,避免直接持有引用
    disaggregation_mode: "DisaggregationMode"
    ps: "ParallelState"
    server_args: "ServerArgs"
    max_total_num_tokens: int
    max_running_requests: int
    pool_stats_observer: "SchedulerPoolStatsObserver"
    tp_worker: "BaseTpWorker"
    token_to_kv_pool_allocator: "BaseTokenToKVPoolAllocator"
    spec_algorithm: "SpeculativeAlgorithm"
​
    # 以下为 Callable getter,用于获取 Scheduler 中的运行时状态
    get_running_batch: Callable
    get_waiting_queue: Callable
    get_stats: Callable
    get_chunked_req: Callable
    get_disagg_prefill_bootstrap_queue: Callable
    get_disagg_prefill_inflight_queue: Callable
    get_disagg_decode_prealloc_queue: Callable
    get_disagg_decode_transfer_queue: Callable
    get_spec_total_num_accept_tokens: Callable
    get_spec_total_num_forward_ct: Callable

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 签名变更遗漏:方法签名从 Scheduler 改为 SchedulerLoadInquirer,若存在未扫描到的调用点(如第三方补丁)可能引发类型错误。
  2. 间接层性能:getter 均为 lambda 闭包,每次调用增加一次函数调用开销,但负载查询不在热路径中,影响可忽略。
  3. 无测试覆盖:本次未新增或修改测试,后续迁移步骤若行为稍有偏差可能无法被 CI 捕获。

对用户和外部 API 无影响,行为完全一致。对开发团队,代码结构更清晰,SchedulerMetricsMixin 职责减轻,为后续拆解 Mixin 奠定基础。对基础设施无影响。

核心路径变更 无测试覆盖 Callable injection 引入间接层

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论