Prhub

#25638 Move module-level helpers out of scheduler.py

原始 PR 作者 fzyzcjy 合并时间 2026-05-18 18:45 文件变更 9 提交数 1 评论 1 代码增减 +180 / -156

执行摘要

将 scheduler.py 的模块级辅助函数移到独立文件

PR body 指出这是对 scheduler.py 中模块级自由项的纯机械迁移,每项都是字节相同地迁移,不重命名、不改签名。目标是将 embedding 结果、dflash 校验、看门狗、空闲睡眠、健康检查以及输出发送等逻辑从庞大的 scheduler.py 中剥离,让调度器核心更聚焦。

值得精读:这是一个教科书式的纯机械重构案例,展示了如何在不改变行为的前提下系统性地提取代码、更新导入关系,并保持字节级等价。对于希望改善大型文件结构的团队有很好的参考价值。

讨论亮点

PR 没有触发实质性 review 讨论,唯一的评论是自动化工具的每日配额提醒。无争议或未解决问题。

实现拆解

  1. 将 EmbeddingBatchResult 数据类及其 copy_to_cpu 方法移至 managers/utils.py,与已有的 GenerationBatchResult 相邻,并一并移入 is_health_check_generate_req 函数(修复反向导入问题)。

  2. 将 validate_dflash_request 函数移至 speculative/dflash_utils.py,与 DFLASH 工具函数放在一起。

  3. 将 create_scheduler_watchdog 函数(含 dump_info 闭包)移至 scheduler_components/invariant_checker.py,紧邻已有检查逻辑。

  4. 将 IdleSleeper 类抽取为独立文件 scheduler_components/idle_sleeper.py,对应 idle_sleeper 组件。

  5. 将 SenderWrapper 类抽取为独立文件 scheduler_components/output_sender.py,对应输出发送组件。

  6. 在 scheduler.py 中删除原有定义,改为从新位置导入;同步调整 batch_result_processor.py、metrics_reporter.py、tokenizer_manager.py 等文件的导入路径。

文件 模块 状态 重要度
python/sglang/srt/managers/scheduler.py 调度器 modified 8.9
python/sglang/srt/managers/scheduler_components/idle_sleeper.py 空闲睡眠 added 8.2
python/sglang/srt/managers/scheduler_components/output_sender.py 输出发送 added 8.12
python/sglang/srt/managers/utils.py 工具函数 modified 7.59
python/sglang/srt/managers/scheduler_components/invariant_checker.py 不变性检查 modified 7.39
python/sglang/srt/speculative/dflash_utils.py DFLASH 工具 modified 6.52

关键符号

IdleSleeper.maybe_sleep SenderWrapper.send_output EmbeddingBatchResult.copy_to_cpu create_scheduler_watchdog validate_dflash_request is_health_check_generate_req

关键源码片段

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

新文件,封装了 IdleSleeper 类,用于降低空闲时 CPU 功耗。

"""idle_sleeper.py — 空闲时降低 CPU 功耗的 poll 机制"""import zmqfrom sglang.srt.environ import envs
from sglang.srt.observability.req_time_stats import real_time
from sglang.srt.platforms import current_platform
​
​
class IdleSleeper:
    """
    在长空闲时段降低系统功耗。当 sglang 无请求时,通过 zmq.Poller 阻塞等待
    而非忙等,从而节省 CPU 资源并留下散热余量。
    """
​
    def __init__(self, sockets):
        # 注册所有接收 socket 到 Poller
        self.poller = zmq.Poller()
        self.last_empty_time = real_time()
        for s in sockets:
            self.poller.register(s, zmq.POLLIN)
        self.empty_cache_interval = envs.SGLANG_EMPTY_CACHE_INTERVAL.get()
​
    def maybe_sleep(self):
        # 阻塞 1000ms 等待事件,避免忙等
        self.poller.poll(1000)
        # 若超过间隔阈值,主动清空缓存
        if (
            self.empty_cache_interval > 0
            and real_time() - self.last_empty_time > self.empty_cache_interval
        ):
            self.last_empty_time = real_time()
            current_platform.empty_cache()

评论区精华

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

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

风险与影响

风险极低:所有迁移都是字节相同的复制-粘贴,签名和语义完全不变。主要风险在于是否遗漏了调用方导入路径的更新。但 PR 已逐一修改所有引用点(scheduler.py、tokenizer_manager.py、scheduler_components/batch_result_processor.py、metrics_reporter.py),并且 CI 测试通过。后续 PR #25639 进一步删除了变为死代码的 is_work_request 函数,验证了迁移完整性。

对用户无功能影响。对开发者而言,若用户代码直接引用了 scheduler.py 中的 EmbeddingBatchResult、IdleSleeper、SenderWrapper 等符号,需将导入语句更新到新位置。不过这些符号原本属于内部模块,外部引用可能性不大。代码库整体模块内聚性提升,未来维护更清晰。

无功能变更 导入路径重写 未新增测试

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论