Prhub

#46306 [Rust Frontend] Expose profiler control routes

原始 PR 作者 pranavthakur0-0 合并时间 2026-07-02 16:46 文件变更 11 提交数 4 评论 5 代码增减 +381 / -2

执行摘要

Rust 前端新增 profiling 控制路由

Python 前端已经暴露了 profiling 控制路由,但 Rust 前端未实现。Issue #46092 指出,当设置 VLLM_USE_RUST_FRONTEND=1 时,用户无法通过 vllm bench serve --profile 等流程控制 profiling。该 PR 填补了这一差异,确保 Rust 前端在启用 profiling 时注册 /start_profile 和 /stop_profile 路由,并转发至引擎的 profile utility。

该 PR 值得精读,特别是在 Rust 前端中启用条件路由和通过 utility RPC 调用 Python 引擎的实现方式,为后续类似功能提供了标准模式。同时测试覆盖非常全面(4 个场景),值得学习。设计决策(不支持点式语法)体现了对 Rust 前端职责边界的清晰界定。

讨论亮点

Review 中有一条由 chatgpt-codex-connector 提出的建议(P2),指出当用户使用点式语法(如 --profiler-config.profiler torch)时,profiler_config_json() 会返回 None,导致 Rust 前端未注册路由,但 managed engine 已启用 profiling,造成不一致。BugenZhao 回复明确表示“不期望 Rust native bootstrap 处理这种 CLI 参数格式”,因此维持当前设计,仅支持 --profiler-config <JSON> 的完整 JSON 格式。该讨论已解决,无未关闭项。

实现拆解

  1. CLI 参数扩展(rust/src/cmd/src/cli.rs):在 SharedRuntimeArgs 中新增 profiler_config 字段(Option<ProfilerConfig>),并添加 profiler() 和 profiler_config_json() 方法用于读取配置和序列化。ProfilerConfig 结构体仅解析 profiler 字段,其余字段透传 Python 引擎。

  2. 引擎客户端方法(rust/src/engine-core-client/src/client.rs):在 EngineCoreClient 上添加 start_profile(profile_prefix) 和 stop_profile(profile_prefix) 方法,内部调用 call_utility("profile", (true/false, profile_prefix)),复用已有的 utility RPC 机制。

  3. 路由注册(rust/src/server/src/routes.rs 和新增 rust/src/server/src/routes/profile.rs):在 build_router_with_options 中,当 state.profiler 存在时,注册 /start_profile(POST)和 /stop_profile(POST)路由,指向 profile::start_profile 和 profile::stop_profile。路由处理函数通过 AppState 获取 engine core client,调用对应方法,并处理错误。

  4. Managed Engine 配置转发(rust/src/managed-engine/src/cli.rs):在 rep_partition_managed_engine_args 中处理 --profiler-config 参数,使其透传到 Python 引擎进程。

  5. 测试覆盖:在 rust/src/server/src/routes/tests.rs 和 rust/src/cmd/src/cli/tests.rs 中添加了四类测试:配置解析是否传递到 managed engine、frontend args-json 启用/禁用 profiling、路由发送正确 utility 调用、以及 profiling 禁用时路由不注册。

文件 模块 状态 重要度
rust/src/server/src/routes/profile.rs 路由处理 added 7.75
rust/src/engine-core-client/src/client.rs 客户端 modified 7.09
rust/src/cmd/src/cli.rs CLI 层 modified 7.18
rust/src/server/src/routes/tests.rs 服务端测试 modified 8.26
rust/src/cmd/src/cli/tests.rs CLI 层测试 modified 8.16

关键符号

start_profile stop_profile with_profiler profiler profiler_config_json start_profile_route_sends_expected_utility_call stop_profile_route_sends_expected_utility_call profile_routes_are_hidden_when_profiling_is_disabled serve_args_forward_profiler_config_to_managed_engine frontend_args_json_enables_profiling_when_profiler_config_set

关键源码片段

rust/src/server/src/routes/profile.rs entrypoint

新增文件,定义了 `/start_profile` 和 `/stop_profile` 的路由处理函数,是路由功能的完整入口。

use std::sync::Arc;
​
use axum::extract::State;
use axum::http::StatusCode;
use tracing::info;
​
use crate::error::ApiError;
use crate::state::AppState;
use crate::utils::utility_call_error;
​
/// 启动 profiling:通过 engine core client 调用 RPC,传入 `true` 表示启动。
pub async fn start_profile(State(state): State<Arc<AppState>>) -> Result<StatusCode, ApiError> {
    info!("starting profiler");
    state
        .engine_core_client()
        .start_profile(None) // 向引擎发送 start_profile 请求
        .await
        .map_err(|error| utility_call_error("start_profile", error))?;
    info!("profiler started");
    Ok(StatusCode::OK)
}
​
/// 停止 profiling:调用 RPC 传入 `false` 表示停止。
pub async fn stop_profile(State(state): State<Arc<AppState>>) -> Result<StatusCode, ApiError> {
    info!("stopping profiler");
    state
        .engine_core_client()
        .stop_profile(None)
        .await
        .map_err(|error| utility_call_error("stop_profile", error))?;
    info!("profiler stopped");
    Ok(StatusCode::OK)
}
rust/src/engine-core-client/src/client.rs core-logic

在 EngineCoreClient 中添加了 start_profile 和 stop_profile 两个公用方法,是 Rust 前端与 Python 引擎交互的桥梁。

/// 启动引擎 profiling。
/// 调用 `profile` utility RPC,传入 `(true, profile_prefix)`。
pub async fn start_profile(&self, profile_prefix: Option<&str>) -> Result<()> {
    self.call_utility::<(), _>("profile", (true, profile_prefix)).await?;
    Ok(())
}
​
/// 停止引擎 profiling。
/// 调用 `profile` utility RPC,传入 `(false, profile_prefix)`。
pub async fn stop_profile(&self, profile_prefix: Option<&str>) -> Result<()> {
    self.call_utility::<(), _>("profile", (false, profile_prefix)).await?;
    Ok(())
}
rust/src/cmd/src/cli.rs core-logic

定义 ProfilerConfig 结构体和 SharedRuntimeArgs 中的 profiler_config 字段,是配置入口,影响路由是否注册和 managed engine 参数传递。

/// 最小化 profiler 配置结构,仅读取 `profiler` 字段。
/// 其余字段透传给 Python 引擎。
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct ProfilerConfig {
    /// Profiler 后端类型(如 "torch"、"cuda")。
    pub profiler: Option<String>,
    // 其他字段被接受但忽略
}
​
// 在 SharedRuntimeArgs 中新增字段
#[arg(long, value_parser = parse_json::<ProfilerConfig>, value_name = "JSON")]
#[serde(default)]
pub profiler_config: Option<ProfilerConfig>,
​
impl SharedRuntimeArgs {
    /// 返回 profiler 类型(如果启用)。
    pub fn profiler(&self) -> Option<String> {
        self.profiler_config.as_ref().and_then(|c| c.profiler.clone())
    }
​
    /// 返回 profiler 配置的 JSON 字符串,用于传递给 managed engine。
    pub fn profiler_config_json(&self) -> Option<String> {
        self.profiler_config
            .as_ref()
            .map(serde_json::to_string)
            .transpose()
            .expect("profiler config serialization should not fail")
    }
}

评论区精华

点式语法 profiler-config 支持 设计

Codex 自动建议指出,当用户使用点式语法 `--profiler-config.profiler torch` 时,`profiler_config_json()` 会返回 None,但 managed engine 仍可能收到这些参数,导致 Rust 前端路由未注册而引擎已启用 profiling。

结论:BugenZhao 回复“我们不期望 Rust native bootstrap 处理这种 CLI 参数格式”,明确不支持点式语法,仅接受完整 JSON 格式。设计上保持简洁,避免增加解析复杂度。 · 已解决

风险与影响

风险较低。路由仅在 profiler 字段非空时注册,生产环境默认不暴露。CLI 参数使用 value_parser = parse_json,JSON 解析失败会直接报错,不会静默忽略。profiler_config_json() 中使用 expect 序列化,失败则 panic,但 ProfilerConfig 由 serde 派生,序列化预期不失败。测试覆盖了配置解析、路由注册和 utility 调用,回归风险小。唯一边界是:如果用户通过 args-json 传递 profiler_config 但格式不符,可能 panic,但属于同一进程内的合理错误处理。

对用户:使用 Rust 前端的用户现在可获得与 Python 前端一致的 profiling 控制能力(vllm bench serve --profile 可正常工作)。对系统:增加两个 HTTP 路由,内存占用可忽略。对团队:完善了 Rust 前端的功能对等性,为后续更多参数的透传提供了参考模式(如添加 CLI 字段 + 序列化 + 条件路由)。

配置传递边界 序列化可能 panic 路由条件注册

关联 Issue

#46092 [Feature]: Rust frontend profiler routes

完整报告

参与讨论