Prhub

#29098 Extract profile request cleanups

原始 PR 作者 merrymercy 合并时间 2026-06-25 02:22 文件变更 16 提交数 2 评论 13 代码增减 +179 / -202

执行摘要

统一 ProfileReqInput 为 ProfileReq 并清理接口

PR body说明:"Extracted from #28688 without bringing in the pickle -> msgspec migration." 当前ProfileReqInput和ProfileReq两个类功能重叠,字段冗余,导致多处入口重复构造参数。统一后可减少重复代码,为后续msgspec迁移奠定基础。

推荐阅读 io_struct.pycommon.py 中的重构模式。核心设计决策包括:① 将 ProfileReqType 枚举作为 ProfileReq 的成员,避免外部重复定义;② 通过 normalize_serialized_named_tensor_payloads 统一多来源tensor数据的格式,可以作为一种数据清洗模式在其他场景复用。

讨论亮点

未发现实质性的review讨论。PR主要由作者直接合并,仅通过issue评论区协调CI重测(/rerun-test)。

实现拆解

  1. 统一数据结构:在 python/sglang/srt/managers/io_struct.py 中,将 ProfileReqInput 的字段合并到 ProfileReq,并删除原 ProfileReqInput 和旧 ProfileReq 类;新增 ProfileReqType 枚举作为 req_type 字段的类型。将 profile_command 字段统一为 req_type

  2. 简化入口参数:在 http_server.pyencode_server.pyengine.pygrpc_bridge.py 等入口点,将原先展开为多个关键字参数调用 start_profile 的方式,改为直接传递 ProfileReq 对象。在 tokenizer_control_mixin.py 中,start_profile 方法签名也从10个参数简化为单个 req 参数。

  3. 新增tensor payload规范化工具:在 common.py 中添加 SerializedTensorPayload 类型别名、_looks_like_pickle_payload 启发式检测函数,以及 normalize_serialized_named_tensor_payload/payloads 两个函数,用于将不同格式的序列化tensor统一为原始pickle字节流。并在 tokenizer_control_mixin.pyupdate_weights_from_tensor 中调用该规范化。

  4. 测试同步:更新 test_profile_merger_http_api.py 中的测试用例,将所有 ProfileReqInput 替换为 ProfileReq,并改用 CustomTestCase。调整 test_profile_merger.py 中的微小差异。

文件 模块 状态 重要度
python/sglang/srt/managers/io_struct.py IO 结构 modified 7.41
python/sglang/srt/utils/common.py 工具函数 modified 7.72
test/registered/unit/managers/test_profile_merger_http_api.py 测试集成 modified 7.53
python/sglang/srt/disaggregation/encode_server.py 编码器分发 modified 7.28
python/sglang/srt/entrypoints/http_server.py HTTP 入口 modified 6.79

关键符号

_looks_like_pickle_payload normalize_serialized_named_tensor_payload normalize_serialized_named_tensor_payloads start_profile_async (http_server.py) start_profile_async (encode_server.py) TokenizerManager.start_profile TokenizerManager.stop_profile ProfileReq.__init__

关键源码片段

python/sglang/srt/managers/io_struct.py core-logic

核心数据类统一:合并 ProfileReqInput 和 ProfileReq,新增 req_type 字段,删除冗余类。

# python/sglang/srt/managers/io_struct.py - 合并后的 ProfileReq 定义class ProfileReqType(Enum):
    START_PROFILE = 1
    STOP_PROFILE = 2
​
​
@dataclass
class ProfileReq(BaseReq):
    req_type: ProfileReqType = ProfileReqType.START_PROFILE # 统一命令字段
    # The output directory
    output_dir: Optional[str] = None
    # Specify the steps to start the profiling
    start_step: Optional[int] = None
    # 若设置,自动在指定步数后停止,无需调用 stop_profile
    num_steps: Optional[int] = None
    # The activities to record. 可选值:"CPU", "GPU", "MEM", "RPD"
    activities: Optional[List[str]] = None
    # 是否按 stage(prefill/decode)分别 profiling
    profile_by_stage: bool = False
    # 是否记录操作符的源代码信息(文件、行号)
    with_stack: Optional[bool] = None
    # 是否记录操作符的输入形状
    record_shapes: Optional[bool] = None
    # 用于关联同一轮 profiling 在多个组件中的 ID
    profile_id: Optional[str] = None
    # 是否合并所有 rank 的 profile 为一个 trace
    merge_profiles: bool = False
    # profile 文件名的前缀
    profile_prefix: Optional[str] = None
    # 仅 profiling 指定的 stages,其余忽略
    profile_stages: Optional[List[str]] = None

评论区精华

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

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

风险与影响

  1. 核心路径变更风险io_struct.py 是所有profile请求的序列化基础,合并类后若遗漏某处引用可能导致运行时错误。从patch看所有显式引用均已更新,但自定义扩展或下游未同步的代码可能受影响。
  2. 序列化兼容性:新增的 normalize_serialized_named_tensor_payloadstokenizer_control_mixin.py 的权重更新路径中被调用,若输入不符合预期(如意外传入非标准格式),可能引发 TypeError 或解析失败。
  3. 测试覆盖:新增的规范化函数仅有间接测试(通过 test_profile_merger),缺乏独立单元测试。HTTP API测试覆盖了参数流程,但未测试 encode_server.py 中的分发路径。

对用户:无直接功能变化,profile接口的输入输出保持兼容。对系统:代码量净减少(-202行),结构更清晰;ProfileReq 现已成为所有profile请求的唯一载体,降低维护成本。对团队:为即将进行的pickle→msgspec迁移扫清障碍,减少迁移时需要修改的接口数量。

核心数据结构统一 批量引用更新 新增序列化逻辑 缺少独立单元测试

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论