Inference Observability Metric & Trace Reference 核查日期 2026-10-27

从请求进入系统,
到 GPU 内部:
指标落在哪一层

按观测对象拆解推理全链路:从前端网关、引擎调度、KV 分层缓存、PD 交接到底层硬件计数器, 厘清各层指标能回答什么、不能回答什么,以及常见的统计口径陷阱与归因误区。

覆盖栈
NVIDIA Dynamo · vLLM V1 · SGLang · HiCache · LMCache · Mooncake · NIXL
硬件与网络
DCGM / NVML · Nsight · NCCL · RDMA / RoCE 计数器
组织方式
Request level 与 Server level 分离;指标、Trace、Profile 三层证据
证据维度
请求级 / 服务级 · 指标、Trace 与 Profile 交叉印证
SYSTEM MAP / 请求到设备的四层路径 图上标出各层原生指标名
01 入口Ingress
客户端 / 压测器
客户端 TTFT · ITL
含公网 RTT 与流式缓冲
›
网关 Frontend
queued_requests · inflight_requests
frontend_time_to_first_token_seconds
›
KV Router
router_overhead_seconds
router_prefix_hit_rate
R / S请求级 + 网关聚合
02 引擎Engine
Waiting 队列
num_requests_waiting
_by_reason{capacity|deferred}
›
Prefill
request_prefill_time_seconds
prefill_kv_computed_tokens
›
Decode 循环
inter_token_latency_seconds
request_time_per_output_token_seconds
›
Detokenize / 流式输出
e2e_request_latency_seconds
request_success{finish_reason}
R每请求样本
S队列与累计量
03 缓存KV
GPU KV Pool
kv_cache_usage_perc
num_preemptions · retract
↔
Host DRAM (L2/L1)
hicache_host_used_tokens
load_back_duration_seconds
↔
L3 / 远端存储
prefetched_tokens_total
storage_prefetch_unfulfilled{reason}
→
另一节点 (PD)非缓存层
kv_transfer_latency_ms
nixl_xfer_time_seconds
S缓存池 / 操作级
非请求级延迟
04 硬件Hardware
SM / Tensor Core
PROF_SM_ACTIVE
PROF_PIPE_TENSOR_ACTIVE
HBM
PROF_DRAM_ACTIVE
DEV_FB_USED
PCIe / NVLink
PROF_PCIE_RX_BYTES
PROF_NVLINK_TX_BYTES
RDMA NIC / SSD
port_xmit_wait · rnr_nak_retry_err
mooncake_ssd_read_latency_us
S设备 / 端口级
不归属单请求
R 请求级(单请求生命周期) S 服务级(引擎、缓存池与硬件状态) 定位原则 先确认指标层级,再向下收敛根因

越靠近底层硬件,指标的时间粒度越粗,归因跨度也越远:GPU kernel 的执行耗时无法直接推导具体请求在第几个 token 发生了抖动。定位问题时,需沿调用路径逐层收敛证据。

Contents
Metric & Trace Reference 核查日期 2026-10-27
12 个章节 · 19 张图
§ 01Observation Level

观测层级:
一条指标属于请求,还是整台机器

指标名相近,描述的实体可能截然不同。区分指标是刻画单个请求还是整机环境,是建立有效因果链的前提。此处 level 指原始观测对象,而非 Prometheus 汇总存储后的形态。

Request Level
单请求样本
记录单次推理的生命周期与阶段耗时(TTFT、TPOT、排队时间、Request Span)。 原始 Trace 可追溯具体请求;一旦聚合成直方图,导出端仅保留分桶计数,不再保留请求上下文。
Server Level
系统与环境状态
记录引擎实例、缓存池、GPU 或网卡的运行水位与累计操作(排队数、KV 使用率、单次传输耗时、设备利用率)。 反映系统当前承载水温,无法反查具体请求。
FIG 01 / 样本如何变成直方图
维度压缩 进入分桶后丢弃请求上下文 跨实例聚合 必须先合并桶计数再计算分位

样本进入直方图后被折叠进固定边界的分桶,不再保留请求标识。这是为了长期存储与低开销聚合所做的设计取舍;若需排查单条慢请求,应接入 Distributed Trace,不要试图从 _bucket 逆推单个请求。

1.1四种容易混淆的计量单位

同一个请求可能触发多次缓存操作;同一个 batch 又同时服务多个请求;设备指标则以固定周期采样。 这三类“多对多”关系,是指标误读的主要来源。

计量单位典型对象例子能回答不能回答
每请求 一次推理的完整生命周期 time_to_first_token_seconds 用户感知的排队、首字与总耗时分布 GPU 是否被该请求独占
每操作 一次 KV 传输、一次缓存 Get/Put kv_transfer_latency_ms、nixl_xfer_time_seconds 搬运本身的耗时与带宽 请求端到端增量(一次请求可能触发多次操作)
每批次 一次调度 step / 一次 forward iteration_tokens_total、FPM wall_time 单步计算规模、batch 内长度均衡度 某个 token 的归属与单请求延迟
每设备 GPU、HBM、PCIe、网卡端口 DCGM_FI_PROF_DRAM_ACTIVE、port_xmit_wait 资源是否饱和、链路是否拥塞 慢请求的具体身份与调用链

遇到名称含 total 或 num_ 的指标,先核实统计实体是请求、token、block 还是物理字节;直方图则需确认样本粒度是一次请求、一次 I/O 还是单步迭代。单位不同,跨实例聚合的数学方法也截然不同。

命名与导出转换

Python prometheus_client 中,Counter 若注册名未以 _total 结尾,导出时会自动追加 _total, 同时生成 _created;Histogram 会展开为 _bucket、_sum、_count。 OTel 仪表经 Prometheus Exporter 导出时,点号会替换为下划线,例如 lmcache_mp.l1_read 变成 lmcache_mp_l1_read_total。

因此上游文档或源码里的注册名与端点实际暴露的名字常有细微差异。配置告警与 Grafana 仪表盘前,先直接抓取一次 /metrics,以其实际输出的 HELP 与 TYPE 为准。

1.2原生、条件原生与自建

下文的指标分三类,混在一起会导致“文档里有、线上抓不到”的排查成本:

Default
默认注册
服务启动即暴露,无需额外参数。例如 vLLM 的 kv_cache_usage_perc。
Conditional
条件启用
依赖特定版本、Connector 插件、CLI 开关或环境变量(如 --kv-cache-metrics、MC_STORE_CLIENT_METRIC=1)。
Derived
派生计算
由原生计数器比值或速率推导(如命中率、有效带宽),需在 PromQL 中明确分子、分母与统计窗口。
§ 02Time Semantics

时间口径:
TTFT、ITL、TPOT 各自从哪一刻算起

“首 Token 时间 300ms”在客户端、网关和引擎中往往对应不同的时间区间。必须先统一物理起止点再对比数值,避免将统计口径的差异误判为性能波动。

FIG 02 / 同一次请求的三种时间线
流式 客户端收到首段输出即为 TTFT 终点 非流式 客户端需等完整响应,引擎仅计首步 Forward

流式模式下客户端收到首块有效内容即为 TTFT 终点;非流式下客户端必须等待完整响应返回,而引擎内部仍按首步完成时间上报,两者在数值上会产生数量级脱节。而在 PD 分离架构中,KV 传输耗时可能前移至首包等待,也可能隐藏在第一个生成 token 的间隔中。

2.1六个概念,三套边界

概念层级起止 / 含义判读边界
客户端 TTFTR客户端发起请求,到收到首次非空有效输出含外部网络、网关鉴权、路由与流式缓冲;不是引擎 /metrics 的 TTFT
网关 TTFTR请求进入网关,到网关发出首个响应分片含网关排队和路由开销,不含客户端侧公网 RTT
引擎 TTFTR框架定义的引擎请求起点到首 token / 首输出流式与非流式计时终点不同,跨框架不可直接比较
TTFB / 首 SSE 事件RHTTP 首字节或首个 SSE 事件到达客户端可能只是 role: assistant 或空文本帧,不等于首个有效 token
ITLR token 样本请求内相邻输出 token 的间隔与 SSE chunk 间隔不等价(一个 chunk 可含多个 token)
TPOTR 请求样本(E2E − TTFT) / (output_len − 1)每请求只有一个样本,不能用 ITL P99 代替请求级 TPOT P99
E2E latencyR请求起点到生成完成客户端、网关、引擎各自观测的边界不同
分位数不可线性加减

各链路阶段的 P99 既不能简单相加,也不能相减以反推端到端指标。不同指标的 P99 对应完全不同的长尾请求集合,描述的是不同随机变量的统计分布边缘,而非同一批请求的各阶段累加。分析单次请求的真实耗时构成,只能依赖完整的 Trace 上下文。

FIG 03 / 为什么“网关 P99 + 引擎 P99”不成立 示意数据 · 非实测
独立分布 各层 P99 来自不同的慢请求集合 不可线性叠加 端到端长尾无法通过单层分位数加减求得

网关与引擎各自的 P99 分别为 210ms 与 190ms,但端到端 P99 达到 520ms。分位点描述的是整个分布的长尾边界,而非同一批具体请求。在网关遭遇排队的请求,在引擎内部可能执行顺利;反之亦然。拆解单次请求的真实耗时构成,必须依赖携带同一 Trace ID 的调用链,无法通过多组直方图加减求得。

2.2ITL 的样本加权:长输出会放大自己的权重

ITL 是 token 级样本,每个请求贡献 output_len − 1 个样本;TPOT 是请求级样本,每个请求只贡献一个。 只要流量里存在少量超长输出,它们就会在 ITL 分布里占据远超其请求占比的权重。 这会让“ITL P99 变差”与“单请求平均速度变差”指向不同的结论。

FIG 04 / ITL 样本数与请求占比的偏离 拖动调节长请求占比
输出长度基准 短 16 · 中 128 · 长 1024 长文本放大效应 5% 数量的请求可产生超半数样本

仅占 5% 数量的长文本请求,即可在 ITL 样本池中占据逾半数比重。因此 ITL 反映的是整体 Token 流的平稳程度,容易被极端长文本主导;评估终端用户感知的单请求生成速度时,应以请求级样本 request_time_per_output_token_seconds 为准。

2.3四个常见的口径陷阱

陷阱表现正确做法
SGLang 流式 / 非流式 TTFT 不同 同一服务切换 stream 后,观测到的 TTFT 量级变化 流式请求在首段 detokenize 输出准备发送时结束;非流式客户端只能看到完整响应。比较前先对齐请求模式。
SGLang 请求级 TPOT 有过滤条件 短输出请求找不到 TPOT 样本 request_time_per_output_token_seconds 仅记录正常完成、output_len > 1 且非 PD Prefill-only worker 的请求。
PD 分离下首 token 落点漂移 引擎 TTFT 正常,但客户端仍感觉慢 KV 交接与 D 端预分配可能落在首包前,也可能落在首个 ITL。原生引擎 TTFT 正常不能单独排除 PD 传输慢。
把 SSE chunk 间隔当 ITL 网关侧统计的输出间隔比引擎 ITL 更平滑 一个 SSE chunk 可能合并多个 token。要比较推理节奏,必须使用引擎侧 token 级样本。
§ 03Gateway & KV Router

网关与 KV 路由:
把“入口慢”和“引擎慢”分开

多实例与前缀感知架构中,请求需经网关与路由器分发。厘清网关层排队与路由耗时,才能避免将入口选路开销误判为引擎算力瓶颈。

FIG 05 / 请求在网关层的路径与可观测点 以 NVIDIA Dynamo 为例
路由开销 仅度量选路算法,不含网关排队 视图漂移 前缀树与后端真实命中存在时滞

请求经前端网关排队、前缀哈希与 Radix Tree 匹配完成选路,随后分发至工作节点。其中 router_overhead_seconds 仅度量选路本身的算法耗时;请求在网关层的等待时间需结合 queued_requests 观测,不可笼统归入单一的“网关延迟”。

指标层级类型 / 单位作用与边界
dynamo_frontend_time_to_first_token_secondsRH s网关侧 TTFT;与引擎 TTFT 对照可剥离网关排队与跨节点转发
dynamo_frontend_inter_token_latency_secondsRH s网关侧流式输出间隔;受 SSE 合并影响
dynamo_frontend_request_duration_secondsRH s网关侧端到端总耗时
dynamo_frontend_queued_requests / dynamo_frontend_inflight_requestsSG 请求网关排队与在途量;判断洪峰是否卡在限流或路由前
dynamo_frontend_disconnected_clientsSC 连接客户端超时断连累计;配合引擎 abort 排查重试雪崩
dynamo_router_overhead_secondsRH s前缀哈希、Radix Tree 查询与 worker 选路耗时
dynamo_component_router_requests_totalSC 请求路由器分发总请求数,用作流量分母
dynamo_component_router_prefix_hit_rateSG 0–1路由层预测的前缀命中率;属于 Gauge,不可跨实例算术平均

3.1路由视图漂移:预测命中与真实命中的差

路由器的 prefix_hit_rate 是“按本地 Radix Tree 视图预测”的结果,而引擎的 prefix_cache_hits / prefix_cache_queries 才是实际命中的 token 数。 当 worker 的缓存被淘汰、Radix Tree 尚未同步,或新实例尚未建立前缀索引时,两者会出现持续偏差。 偏差本身不是故障,但如果它长期扩大,路由决策就会把请求送到并不命中缓存的 worker, 表现为 Prefill 计算量上升,而路由层仍显示“命中良好”。

FIG 06 / 路由预测命中率与引擎实际命中率 示意数据 · 30 分钟窗口
虚线 路由预测命中率 实线 引擎实际命中 Token 比例 背离诱因 Worker 淘汰或索引同步延迟

两组曲线背离往往预示着路由器的前缀树状态与后端 Worker 发生脱节:例如 Worker 端已因显存压力淘汰了热点 KV 块,而网关尚未收到更新。此时表面上前缀命中预测维持高位,但引擎端的实际 Prefill 计算量已开始攀升。

避免跨层分位数做差

以“网关 TTFT P99 − 引擎 TTFT P99”估算网关自身耗时是常见的统计陷阱。两组分位样本并非同一批请求,所得差值缺乏物理意义。可靠的做法是对同批请求注入统一的 trace_id,在 Trace 系统中计算各层 Span 的单请求耗时差;或直接采集网关自身排队、选路与转发的细分 Span。

§ 04vLLM V1

vLLM V1:
用调度状态串起主链路指标

围绕请求的主状态流转——等待入队、调度分配、Prefill 计算、Decode 迭代直至完成。顺着状态迁移看指标,调度瓶颈一目了然。

FIG 07 / vLLM V1 请求状态与指标落点 统一前缀 vllm:
主路径 等待 → Prefill → Decode → 完成 重算回退 KV 不足触发 Preemption 重新入队

等待队列细分为 capacity 与 deferred,用以区分单纯显存不足与等待异步依赖(如 KV 连接器拉取)。进入运行态后,Prefill 与 Decode 各自记录耗时分布;若触发抢占(Preemption),正在解码的请求会被重置回等待队列并面临重算,直接反映 KV 池容量耗尽。

4.1主链路必看指标

指标(前缀 vllm:)层级类型 / 单位作用与判读边界
time_to_first_token_secondsRH s引擎 TTFT;与网关 / 客户端 TTFT 分开看
inter_token_latency_secondsRH s输出节奏与 Decode 步间抖动;token 级样本
request_time_per_output_token_secondsRH s请求级平均 TPOT;每请求一个样本
e2e_request_latency_secondsRH s引擎内部请求总耗时
request_queue_time_secondsRH sWAITING 队列耗时;判断调度拥塞或 KV 分配等待
request_prefill_time_secondsRH sPrefill 阶段框架耗时
request_decode_time_secondsRH sDecode 阶段框架总耗时
request_inference_time_secondsRH sRUNNING 阶段(Prefill + Decode)总耗时
num_requests_running / num_requests_waitingSG 请求当前执行与排队规模;只反映瞬时水位
num_preemptionsSC 次抢占累计;需结合 KV 使用率判断是否发生重算
kv_cache_usage_percSG 0–1引擎 KV Block Pool 使用比例,不是整卡显存占比
prefix_cache_hits / prefix_cache_queriesSC token本地 APC 前缀缓存命中与查询量
external_prefix_cache_hits / external_prefix_cache_queriesSC token外部 KV Connector 的命中与查询 token 数
prompt_tokens / generation_tokensSC token输入 / 输出 token 累计量,导出带 _total
request_prompt_tokens / request_generation_tokensRH token单请求输入 / 输出长度分布;解释 E2E 变化的重要旁证
request_successSC 请求按 finish_reason 细分;不能作为全部入口请求分母
iteration_tokens_totalSH token/step每个调度 step 的总 token 分布;名字带 total,但类型是 Histogram

Request level 指标均以服务器直方图形式暴露,不保留请求 ID。定位单次慢请求细节需启用 OpenTelemetry Trace。

4.2KV 水位与抢占:高水位不等于故障

kv_cache_usage_perc 长期停在 0.9 以上不一定是问题。高水位意味着缓存被充分利用, 只要没有发生抢占与重算,延迟可以是稳定的。真正需要警惕的是水位触顶后, num_preemptions 开始增长,同时等待队列与 ITL 长尾一起抬升。

FIG 08 / 两种高水位:健康复用与驱逐抖动
健康高水位 缓存饱满且抢占为 0 驱逐抖动 水位触顶伴随持续抢占脉冲

在健康复用状态下,KV 池即便稳定维持在 0.9 以上,抢占速率也保持为 0,吞吐平稳;而在抖动场景中,水位一旦触及 0.99,抢占脉冲随之爆发并导致排队反弹。评判显存压力不能单看使用率均值,关键在于是否引发了请求重算。

排队原因分类

num_requests_waiting_by_reason{reason="capacity"} 指向 KV / 算力槽位不足; reason="deferred" 指向等待异步外部条件。 如果只看 num_requests_waiting,两种完全不同的瓶颈会被合并成同一个“队列变长”。 进一步可用 num_requests_kv_fetch_by_stage{stage} 区分 waiting_to_start、in_progress、completed_waiting 三个阶段。

4.3条件指标:KV 生命周期、缓存来源与 MFU

指标层级开启条件能解释的问题
request_prefill_kv_computed_tokensR默认本次请求实际新算的 Prefill KV token 数(已扣除命中部分)
prompt_tokens_cached_by_source{source}S默认按 device / host / disk / p2p / external 分解缓存命中来源
admission_rejectionsS默认并发上限或队列满导致的直接拒绝
request_num_preemptionsR默认单请求被抢占次数分布;识别是否集中伤害少数长文本请求
kv_block_lifetime_secondsS--kv-cache-metricsKV Block 从分配到淘汰的驻留寿命
kv_block_idle_before_evict_secondsS--kv-cache-metrics淘汰前空闲时长;判断缓存池是否过小导致热块被冲刷
kv_block_reuse_gap_secondsS--kv-cache-metrics同一 Block 相邻两次访问的间隔
estimated_flops_per_gpu_totalS--enable-mfu-metrics每 GPU 估算有效模型算力累计
estimated_read_bytes_per_gpu_total / estimated_write_bytes_per_gpu_totalS--enable-mfu-metrics每 GPU 估算理论显存读写字节数

4.4投机解码:接受率要按位置看

投机解码的收益取决于“提出的候选 token 有多少被 target 模型接受”。 全局接受率 rate(accepted) / rate(draft_tokens) 会掩盖位置差异: 越靠后的候选越难被接受,而每一步验证的计算成本并不会同比下降。

FIG 09 / 按投机步位置拆分的接受 token 数
前序步 位置 0–1 通常命中率最高 深层步 位置 ≥2 边际收益显著衰减

各位置的命中率逐级递减属正常衰减。若业务流量特征变化导致位置 2 之后命中率断崖式下滑,而验证开销固定发生,过大的投机步长反而会拖慢单 Token 生成速度。评估投机收益需细分到具体位置分布,而非仅看单一的整体接受率。

相关指标:spec_decode_num_drafts、spec_decode_num_draft_tokens、 spec_decode_num_accepted_tokens、 spec_decode_num_accepted_tokens_per_pos{position}。 另外 model_forward_time_milliseconds 与 model_execute_time_milliseconds 可区分“单次 forward 计算”与“Worker execute_model 全过程”,后者含输入准备、通信与采样。

Tracing

通过 --otlp-traces-endpoint 启动后,vLLM 会导出请求级 llm_request Span, 并在属性中携带 gen_ai.usage.prompt_tokens、gen_ai.usage.completion_tokens、 gen_ai.response.finish_reasons 以及排队与执行时间戳。 它弥补的正是 Prometheus Histogram 无法关联单个慢请求的限制。

§ 05SGLang & Request Trace

SGLang:请求 Trace
把“慢在哪一段”变成可枚举的阶段

SGLang 将文本分词、调度分派、Prefill 与 Decode 循环乃至跨节点交接拆分为明确的 Span。根据排查场景选择合适的 Trace Level,在观测粒度与运行时开销之间取得平衡。

FIG 10 / 请求级阶段瀑布
Level 2 粗粒度阶段,适合生产采样 Level 3/4 细化到单步与 Forward,需防范 CPU 开销

Level 2 覆盖核心分期,适合生产环境常态采样;Level 3 展开 Decode 循环;Level 4 则为单次 Forward 记录 Span,会带来可观的 CPU 额外开销与 Trace 导出量。在线开启高粒度追踪时,务必配置 SGLANG_TRACE_ASYNC=1,防止 OTLP 导出阻塞调度主线程。

两个 Trace Level 定义

上游 SGLang 将 SGLANG_TRACE_LEVEL 定义为 0–3; 在 NVIDIA Dynamo 的 SGLang 集成中取值为 1–4,默认 2(粗粒度), 3 增加 decode_loop,4 开启逐次 Forward Span。 排查前先确认所用发行版的编号体系,否则“调到 3”在两种体系下对应的粒度不同。

5.1主链路指标

与 vLLM 类似,SGLang 的主链路指标也围绕“排队、Prefill、Decode、结束”组织。 差别主要在命名与过滤条件:token_usage 对应 KV Token Pool 水位, num_retracted_reqs 对应回退,cache_hit_rate 则是 RadixCache 的瞬时快照。

指标(前缀 sglang:)层级类型 / 单位作用与判读边界
time_to_first_token_secondsRH s服务端 TTFT;流式在首段 detokenize 输出时结束,非流式按内部 first_token_time
inter_token_latency_secondsRH s流式输出块 / token 间延迟
request_time_per_output_token_secondsRH s请求级 TPOT;仅成功完成、output_len > 1 且非 PD prefill-only worker 时计入
e2e_request_latency_secondsRH s引擎侧请求端到端总耗时
queue_time_secondsRH s请求在 Scheduler 队列中的等待耗时
per_stage_req_latency_seconds{stage}RH s开启请求级阶段统计后,按 stage 标签拆分的阶段延迟
num_running_reqs / num_queue_reqsSG 请求当前运行中与等待队列中的请求数
num_used_tokens / token_usageSG token / 0–1KV Token Pool 已用 token 与占用比例;混合架构另有 full_token_usage、swa_token_usage、mamba_usage
cache_hit_rateSG 0–1RadixCache 近期命中率快照;Gauge 不可跨实例直接求算术平均
cached_tokens_total{cache_source}SC token按 device、host、storage 统计的命中缓存 token 累计
gen_throughputSG token/s引擎统计窗口内的生成吞吐速率
num_retracted_reqs / num_retracted_requests_totalSG 请求 / C 次当前回退请求数与累计回退;另有 input / output token 维度
spec_accept_rate / spec_accept_lengthSG 0–1 / token投机解码接受率与平均每轮接受 token 长度(含 1 个 target bonus token)
is_cuda_graph / cuda_graph_passesSG 布尔 / C 次当前是否命中 CUDA Graph 及累计执行步数;排查跌出 Graph 导致的抖动
num_grammar_queue_reqs / grammar_compilation_time_secondsS / RG 请求 / H s结构化输出(JSON Schema / Regex)语法编译排队数与耗时
forward_execution_seconds_totalSC s模型 Forward 执行累计秒数
estimated_flops_per_gpu_total / estimated_read_bytes_per_gpu_totalSC FLOPs / bytes每 GPU 算力与显存读写估算累计

cache_hit_rate 是瞬时 Gauge,不能跨实例直接求算术平均。计算集群整体命中率时,应分别对各实例的命中 Token 与总 Token 求和,再做除法。

5.2原生阶段与链路对应

阶段名(含版本演进)对应链路典型判读
tokenizeTokenizer 文本切词变长而队列不涨,指向 CPU 切词或分词器竞争
api_server_dispatch(旧名 dispatch)API Server 向 Tokenizer / Engine 分派与 tokenize 同升,多为 Host 侧瓶颈
dpc_dispatch(旧名 dc_dispatch)Data Parallel Controller 路由分派DP 场景下定位跨控制器转发开销
mm_encode多模态输入编码图像 / 视频请求专属,常表现为个别请求的长尾
request_process调度器请求预处理与调度队列状态一起看
prefill_waitingPrefill 队列等待与 num_queue_reqs 同升说明排队
prefill_forwardPrefill Forward 执行变长才下钻到 batch 与 GPU
chunked_prefill分块 Prefill 复合阶段长输入被拆分时的组合耗时
decode_forward / decode_loop单步 / 多步 Decode高粒度 Trace 下逐次输出,注意采集开销
spec_draft / spec_verify投机解码 Draft 与验证与接受率指标对照,判断投机是否负优化
prefill_prepare / prefill_bootstrapPD 下 P 端准备与握手堆积在握手阶段而非数据搬运
prefill_transfer_kv_cachePD 下 P 端发起 KV 传输与 kv_transfer_latency_ms 对照
decode_prepare / decode_bootstrapPD 下 D 端预分配与握手预分配失败会反压 P 端
decode_waiting / decode_transferredD 端等待传输与接管waiting 长说明传输或调度未就绪

5.3Retract:Token Pool 触顶后的回退链

SGLang 在 KV Token Pool 不足时会把已运行的请求回退(retract),释放其占用的 token, 后续再重新计算。它和 vLLM 的 preemption 类似,但指标名不同: num_retracted_reqs、num_retracted_requests_total、 num_retracted_input_tokens_total / output_tokens_total。

Trigger
Token Pool 告罄
并发 Decode 持续消耗 KV Token,token_usage 逼近 1.0 上限。
Action
请求回退与重算
num_retracted_reqs 递增,被回退请求释放 Token 并重新排队 Prefill。
Impact
ITL 偶发尖刺
重算导致单请求生成停顿,inter_token_latency_seconds 长尾显著抬升。
Remedy
并发约束或扩池
调小 max_running_requests,或扩充单卡 KV 容量与部署规模。
Forward Pass Metrics(FPM)

Dynamo / SGLang 还通过 ZMQ(默认端口 20300)发布逐 iteration 的结构化事件。 它不是按请求导出的 Prometheus Histogram,而是批次级事件: wall_time、scheduled_requests.sum_prefill_tokens、 var_prefill_length、sum_decode_kv_tokens、var_decode_kv_tokens 等。 这些字段解释的是“这一步 batch 长什么样”,包括长度方差导致的 Attention 负载不均。

§ 06KV Cache Hierarchy

KV 分层与卸载:先统一命名,再谈命中率

前缀复用、分层卸载与 PD 交接属于三种不同性质的数据流转。各框架对 L0 / L1 / L2 缓存层级的定义互有出入,推导命中率前须先对齐物理存储介质与分子分母口径。

KV 流转概念辨析

Prefix reuse 避免 Prefill 重复计算,命中发生于单引擎前缀缓存; Offload / Reload 在 GPU HBM、Host DRAM、远端存储或本地磁盘间迁移动态数据; PD handoff 则负责在 Prefill 与 Decode 节点间移交上下文(见 PD 分离)。 三类动作均属于操作级(Server level)度量,不应直接等同于请求端到端延迟。

6.1同一层,不同名字

物理层级SGLang HiCacheLMCache MPvLLM Connector / OffloadMooncake
GPU HBM L1(GPU KV Pool) L0 GPU KV Cache 通常不驻留(作为传输源 / 目的)
本地 Host DRAM L2(Host Pool) L1 Simple CPU Offload Pool / HiSparse Host Cache Store Client 的本地缓冲(非持久层)
本地磁盘 / 远端存储 L3(外部存储) L2(外部 / 远端插件) 外部 KV Connector(NIXL 等) Store 集群 + SSD 层
跨节点 KV PD handoff / P2P 传输,不属于本地缓存层级 NIXL / P2P Connector Transfer Engine(RDMA / TCP / NVLink)

HiCache 的 L1 对应 GPU、L2 对应 Host;而 LMCache MP 的 L0 对应 GPU、L1 对应 Host、L2 对应外部存储。跨组件交流或配置监控时需统一词汇,避免单提“L1 命中率”引发歧义。

6.2分层缓存与搬运路径

FIG 11 / KV 分层与各段搬运指标 点击层级查看对应指标
分层原则 越靠近硬件带宽越高、容量越小 开销权衡 回载占用总线带宽并与计算争用

分层缓存以 PCIe / NVLink 带宽为代价换取更大的前缀留存窗口。每次回载(Load Back)都会与模型推理争用总线与显存带宽;若命中带来的计算减免无法覆盖搬运延时,卸载反倒会拖累整体吞吐。

FIG 12 / Lookup 命中不等于 Retrieve 命中 示意数据 · 1000 次查询
索引命中 ≠ 数据就绪 查询与读取之间存在并发驱逐窗口 排查定位 区分索引失效与预取超时

Lookup 命中仅证明索引记录存在,但在异步发起的读取执行前,目标块可能已被驱逐。LMCache Legacy 的 lookup_hit_rate 与 retrieve_hit_rate 统计分母并不相同;在 MP 架构中,还需结合 l1_read_failure(并发竞态驱逐)与 l2_prefetch_failure 的具体原因定位损耗。

6.3HiCache:三段迁移与丢弃

指标(前缀 sglang:)方向类型 / 单位判读
hicache_host_used_tokens / hicache_host_total_tokens容量G tokenHost 池水位;触顶后会出现丢弃
evicted_tokens_total / eviction_duration_secondsGPU → 淘汰C token / H sGPU 侧淘汰量与耗时
hicache_backup_tokens_total / hicache_backup_duration_secondsGPU → HostC token / H s备份速度是否跟得上淘汰速度
load_back_tokens_total / load_back_duration_secondsHost → GPUC token / H s回载量与时延;仅覆盖 Stream Copy
load_back_bytes_total / hicache_backup_bytes_total物理字节C bytes各 TP Rank 自身的 shard 流量
prefetched_tokens_total / prefetch_bandwidthL3 → HostC token / H GB/s预取完成量与带宽
storage_prefetch_hit_tokens_totalL3 查询C token查询命中,尚不等于已加载可用
storage_prefetch_unfulfilled_tokens_total{reason}L3 未完成C token-attemptdeadline / host_capacity / transfer
hicache_dropped_tokens_total备份失败丢弃C tokenL1 淘汰时尚未完成 L2 备份即被覆盖
跨 Rank 聚合规则

逻辑 token 指标(如 load_back_tokens_total)在同一组 TP Rank 上记录相同数值, 跨实例聚合时必须限定 tp_rank="0"。 物理字节指标(如 load_back_bytes_total)记录各 Rank 自身的 KV shard 流量, 求整机带宽时应跨全部 TP Rank 求和。 混用两种口径,会得到整数倍的偏差。

6.4LMCache Legacy:In-Process 的操作级指标

Legacy 模式在推理进程内运行,指标前缀为 lmcache:; MP 模式把缓存拆成独立进程,改用 OTel 命名 lmcache_mp.*。 两者都区分 Lookup、Retrieve、Store 三类操作,但命中率的分母不同,看板不能混用。

指标(前缀 lmcache:)类型 / 单位作用与判读边界
num_lookup_requests / num_retrieve_requests / num_store_requestsC 次Lookup、Retrieve、Store 三类缓存 API 调用次数
num_lookup_tokens / num_lookup_hits / lookup_hit_rateC token / G 0–1Lookup 查询与命中的 token 数及瞬时命中率
num_requested_tokens / num_hit_tokens / retrieve_hit_rateC token / G 0–1Retrieve 阶段实际拉取命中的 token 数;分母与 Lookup 不同
num_stored_tokensC token实际写入缓存的 token 总数
time_to_lookup / time_to_retrieve / time_to_storeH s三类操作的耗时分布
retrieve_speed / store_speedH token/sRetrieve 与 Store 的速率分布
retrieve_to_gpu_time / store_from_gpu_time / store_put_timeH sCPU / Buffer → GPU 拷贝、GPU → CPU 拷贝及后端 Put 耗时
remote_time_to_get / remote_time_to_put / remote_time_to_get_syncH s远端后端(Mooncake / Redis / InfiniStore)Get / Put 与同步等待
remote_backend_batched_get_blocking_timeH s远端批量 Get 阻塞主路径的时间
local_cache_usage / remote_cache_usage / local_storage_usageG bytes本地 CPU 缓存、远端缓存与本地磁盘已用字节数
local_cpu_evict_count / local_cpu_evict_failed_count / forced_unpin_countC 次淘汰次数、淘汰失败与超时强制 Unpin;排查内存泄漏与死锁
num_p2p_requests / num_p2p_transferred_tokens / p2p_time_to_transfer / p2p_transfer_speedC 次 / token, H s, token/s跨实例 P2P KV 传输次数、token 数、耗时与速率

Legacy 采集进程内的缓存调用;MP 则聚焦独立进程中的共享池与异步任务队列。Legacy 下命中率下滑重点排查 time_to_retrieve 与 CPU 驱逐;MP 下则重点分析 l1_read_failure 与 l2_prefetch_failure 的错误标签。

6.5LMCache MP:L0 / L1 / L2 与在途任务

OTel 注册名类型 / 单位作用与边界
lmcache_mp.lookup_requested / .lookup_hitC key查询与命中的 chunk key 数
lmcache_mp.lookup_hit_l1 / .lookup_hit_l2C keyL1 命中,以及 L1 未命中但 L2 命中的条件互斥计数
lmcache_mp.l1_read / .l1_write / .l1_evictedC chunkL1 内存池读写与淘汰 chunk 数
lmcache_mp.l1_memory_usage_bytes / .l1_usage_ratioG bytes / 0–1L1 池水位
lmcache_mp.l1_chunk_lifetime / .l1_chunk_idle_before_evict / .l1_chunk_evict_reuse_gapH s驻留寿命、淘汰前空闲、淘汰后再次被请求的“遗憾间隔”
lmcache_mp.l2_store_submitted / .l2_store_completedC 请求L2 异步写提交与完成;单位是请求,不是 chunk
lmcache_mp.l2_prefetch_load_completed / .l2_load_completedC chunk成功加载 chunk 数;不能直接除以提交数算成功率
lmcache_mp.active_prefetch_jobs / .num_inflight_l2_stores / .num_inflight_l2_loadsG 任务在途任务与队列压力
lmcache_mp.l0_l1_store_throughput / .l0_l1_load_throughput / .l2_load_throughputH GB/s各段吞吐分布
lmcache_mp.transfer_phase_bytes{phase} / .transfer_phase_elapsed{phase}C bytes / H s按内部阶段拆分的传输量与时延
lmcache_mp.l1_allocation_failure / .l1_read_failure / .l2_prefetch_failure{reason}C 次L1 容量满、查后读前被淘汰、L2 预取失败

6.6vLLM Connector:NIXL、Simple Offload 与 HiSparse

指标(前缀 vllm:)类型 / 单位作用与边界
nixl_xfer_time_seconds / nixl_post_time_secondsH s数据搬运耗时与描述符提交耗时分开看
nixl_bytes_transferred / nixl_num_descriptorsH bytes / 个单次传输规模与散列描述符数量;累计流量取 _sum
nixl_num_failed_transfers / nixl_num_failed_notificationsC 次数据传输与握手通知失败
nixl_num_kv_expired_reqs / nixl_num_notifications_after_expiryC 请求 / 次KV 租约过期,以及过期后才到达的 D 端通知
simple_kv_offload_load_blocks_totalC block从 CPU Offload Pool 恢复到 GPU 的 Block 数
simple_kv_offload_save_outcomes_total{outcome}C 次保存结果:写入、跳过或池满丢弃
simple_kv_offload_pending_store_blocks / .used_blocksG block待写出积压与 CPU 池已用
hisparse_cache_hits / .hisparse_cache_missesC 次稀疏缓存命中 / 未命中
hisparse_host_cache_usage_perc / .hisparse_pending_page_transfersG 0–1 / 次Host 缓存水位与在途页迁移
hisparse_host_block_lifetime_seconds / .hisparse_host_block_reuse_gap_secondsH sHost Block 寿命与复用间隔
回载链路分段定位

HiCache H2D 回载耗时拉长通常对应三类不同根因: (1) PCIe / NVLink 总线被计算算子或其他数据拷贝争用; (2) 前置 Fence 与 Stream 同步阻塞; (3) 缓存块已就绪但调度器尚未批复 GPU 槽位。 排查时,第一类比对 load_back_bytes_total 与耗时比值,并对照 DCGM_FI_PROF_PCIE_RX_BYTES; 第二类观察同步等待并结合请求排队; 第三类则直接核对 num_requests_kv_fetch_by_stage{stage="completed_waiting"}。

§ 07Prefill–Decode Disaggregation

PD 分离:
一次请求,两个节点上的两段时间

PD 分离解耦了计算特征截然不同的 Prefill 与 Decode 节点,通过网络搬运 KV。新的队列、握手与租约状态使首 Token 延迟的构成跨越了节点边界。

FIG 13 / P 端与 D 端的交接时序
时序重叠 握手与部分传输可与计算流水并行 非线性累加 单段延迟不可简单相加推导 TTFT

Prefill 完成后,D 端需先行预分配 KV 空间并完成 Bootstrap 握手,再发起网络拉取。各阶段操作常与计算重叠执行,因此 bootstrap_ms、alloc_ms 与 latency_ms 无法通过简单的标量累加换算为客户端的 TTFT 增量。

指标(前缀 sglang:)端类型 / 单位作用与边界
num_prefill_bootstrap_queue_reqsPG 请求等待与 D 端完成 Bootstrap 握手
num_prefill_inflight_queue_reqsPG 请求已完成计算、传输中或等待确认释放 KV
num_decode_prealloc_queue_reqsDG 请求等待本地 KV Token Pool 预分配空间
num_decode_transfer_queue_reqsDG 请求已分配空间,等待 KV 传输完成
pending_prealloc_token_usageDG 0–1已预分配但尚未 Decode 的 token 占比;识别虚占
kv_transfer_bootstrap_msP/DH ms握手耗时;单位是毫秒
kv_transfer_alloc_msDH msD 端 KV 空间分配等待
kv_transfer_latency_msP/DH ms跨节点数据搬运
kv_transfer_speed_gb_s / kv_transfer_total_mbP/DH GB/s / MB单次传输有效带宽与数据量
num_bootstrap_failed_reqs_total / num_transfer_failed_reqs_totalP/DC 请求握手失败与传输失败累计
num_prefill_retries_totalPC 次因握手或传输失败触发的 Prefill 重试

SGLang 的 kv_transfer_* 系列以毫秒导出,与秒级 TTFT 同图展示前必须先除以 1000 换算量纲。

7.1D 端预分配反压:一个典型的级联死锁前兆

FIG 14 / 预分配不足如何反压回 P 端 因果链 · 非调用链
级联效应 D 端排队反压导致 P 端显存锁定 排查重点 优先降低 D 端水位而非扩容 P 端

D 端显存水位过高会导致预分配等待,kv_transfer_alloc_ms 攀升;这会直接导致 P 端已完成计算的请求无法交接,已算好的 KV 显存被锁定在 inflight 队列中。当 P 端也耗尽空闲块时,两端将形成互等停滞。排查此类卡顿应优先从 D 端回收或限流切入,而非盲目扩容 P 端。

7.2NIXL:租约、通知与失败路径

vLLM 的 PD 传输通常经 NIXL 完成。除了 nixl_xfer_time_seconds 这类搬运耗时, 还需要关注控制面的失败语义:KV 租约超时、过期后才到达的通知、以及传输失败计数。

现象先看对照边界
KV 在 D 端拉取前已过期 vllm:nixl_num_kv_expired_reqs nixl_num_notifications_after_expiry;num_requests_kv_fetch_by_stage D 端排期过晚,P 端已按超时回收;不是网络慢
握手通知失败 vllm:nixl_num_failed_notifications NIC rnr_nak_retry_err 接收队列未就绪或内存注册不足
传输耗时长但带宽正常 nixl_xfer_time_seconds、nixl_num_descriptors nixl_post_time_seconds KV 块碎片化导致小包 Scatter-Gather 开销大,而非链路拥塞
传输失败后重试 nixl_num_failed_transfers P 端 num_prefill_retries_total 重试会重复消耗 Prefill 算力,需与排队指标一起判断
PD 架构下首 Token 归属

由 D 节点直回首包时,KV 传输与预分配开销会计入客户端 TTFT; 若架构选择由 P 节点直回首包,该段等待将平移至首个生成 Token 的 ITL 样本中。 因此在 PD 分离场景中,引擎端上报的 TTFT 正常并不能直接排除跨节点传输慢,需结合首步 ITL 与 kv_transfer_latency_ms 综合判断。

§ 08GPU & Hardware Counters

GPU:
利用率接近 100%,并不代表算力被用满

GPU_UTIL 仅反映采样窗口内是否存在活跃的 Kernel,无法衡量 Tensor Core 的实际负载。理清采样机制,方能解释“利用率虚高而吞吐受阻”的反常现象。

Sampling Window
采样时间窗口
NVML 的 GPU_UTIL 表示采样周期内任意 SM 处于活跃状态的时间比例(窗口通常在 1/6 秒至 1 秒)。短促的算子执行与周期性空闲易被统计窗口抹平。
Blind Spot
单 SM 活跃即打满
只要采样周期内持续有哪怕一个最小粒度的 Kernel 运行,利用率读数即可顶满 100%,完全无法区分全卡张量运算与轻量调度算子。
FIG 15 / 同样的 100%:SM 占用示意 8 × 4 SM 网格
利用率失真 单 SM 活跃即可触发 100% GPU_UTIL 算力实态 需以 SM_ACTIVE 与 Tensor 流水线为准

即使整张 GPU 仅有单个 SM 运行微小 Kernel,NVML 的 GPU_UTIL 也能直接显示为 100%;此时 SM_ACTIVE 与 PIPE_TENSOR_ACTIVE 则暴露了真实的算力闲置。评估硬件饱和度必须依赖更深层的 Profiling 计数器,不能轻信宿主机层面的设备利用率。跨节点传输证据见 网络与存储后端。

8.1四种典型场景的指标组合

FIG 16 / 场景对照:同样的卡,不同的瓶颈
Memory-Bound DRAM 高、Tensor 低(长文本 Decode) Compute-Bound Tensor 与 DRAM 齐高(高吞吐 Prefill)

虽然四种工况下的表面利用率均接近打满,背后的物理制约却截然不同:长上下文 Decode 受限于显存带宽(DRAM 高、Tensor 低);通信或 Launch 开销受制于同步等待(SM 与 Tensor 双低);唯有大 Batch Prefill 才能同时将计算流水线与显存带宽推至高效区间。

8.2DCGM 指标与默认采集边界

导出名默认 CSV类型 / 单位含义与判读边界
DCGM_FI_DEV_GPU_UTIL开启G 0–100%采样周期内任意 SM 有 kernel 的比例;不代表算力饱和
DCGM_FI_PROF_GR_ENGINE_ACTIVE开启G 0–1图形 / 计算引擎活动时间比例
DCGM_FI_PROF_SM_ACTIVE需取消注释G 0–1全部 SM 存在驻留 warp 的周期比例均值;等 HBM 的 warp 也计入
DCGM_FI_PROF_SM_OCCUPANCY需取消注释G 0–1平均驻留 warp 数与硬件上限之比
DCGM_FI_PROF_PIPE_TENSOR_ACTIVE开启G 0–1Tensor Core 流水线活动比例;不等于有效 MFU
DCGM_FI_PROF_DRAM_ACTIVE开启G 0–1HBM 总线有读写事务的比例;不是显存容量占比
DCGM_FI_DEV_FB_USED / FB_FREE开启G MiB整卡 HBM 已用 / 空闲;含权重、CUDA Context、缓存池与 KV Pool
DCGM_FI_DEV_MEM_COPY_UTIL开启G 0–100%显存控制器忙碌比例;不是 PCIe DMA 引擎独占利用率
DCGM_FI_PROF_PCIE_TX_BYTES / RX_BYTES开启G bytes/s已是速率 Gauge,不要套 rate()
DCGM_FI_PROF_NVLINK_TX_BYTES / RX_BYTES需取消注释G bytes/s已是速率 Gauge,不要套 rate()
DCGM_FI_DEV_SM_CLOCK / MEM_CLOCK开启G MHz实时频率;与降频原因一起看
DCGM_FI_DEV_CLOCK_THROTTLE_REASONS开启G 位掩码功率墙、温度墙等降频原因
DCGM_FI_DEV_POWER_USAGE / TOTAL_ENERGY_CONSUMPTION开启G W / mJ实时功耗与累计能耗;能量需除以 1000 转为焦耳
DCGM_FI_DEV_XID_ERRORS开启G 错误码值是最后一次触发的 XID 编号,不是次数,严禁求 rate()
DCGM_EXP_XID_ERRORS_TOTAL开启C 次XID 事件计数,统计频次应使用它
DCGM_FI_DEV_PCIE_REPLAY_COUNTER开启C 次PCIe 链路重放;增量大于 0 指向物理链路问题

官方 dcgm-exporter 容器默认 CSV 仅启用基础指标。SM_ACTIVE、SM_OCCUPANCY、NVLINK_TX/RX_BYTES 默认被注释,需通过挂载自定义字段配置文件显式导出。

8.3单位与聚合陷阱

陷阱原因正确做法
对 PCIe / NVLink 速率套 rate()这些指标本身已是 bytes/s Gauge直接取值或做平均;累计流量用对应的 *_BYTES_TOTAL
把 FB_USED 当作 KV 使用率整卡显存包含权重、上下文、缓存池与碎片引擎 KV 压力看 kv_cache_usage_perc 或 token_usage
对 XID 指标求 rate()值是错误码编号,不是计数用 DCGM_EXP_XID_ERRORS_TOTAL 统计频次
把 GPU_UTIL 当作 MFU只表示有 kernel 在跑结合 PIPE_TENSOR_ACTIVE、DRAM_ACTIVE 与 Nsight
跨卡平均 SM_ACTIVE 判断 TP 瓶颈慢卡会被平均值掩盖逐卡对比,找 Straggler

8.4Profile 的层级与代价

工具层级能看到什么限制
Nsight Systems nsysS 线程 / Stream / KernelCPU 发射延迟、Stream 排队、Kernel 宽度、Memcpy 方向、GPU BubbleCPU 侧 NVTX Range 宽度不等于设备端 Kernel 执行时间
Nsight Compute ncuS 单 KernelWarp Stall、SM / DRAM / L2 吞吐、寄存器与共享内存限制、Roofline 位置触发 Kernel Replay 并锁频,严重改变线上延迟;仅限离线或单步采样
CUDA Event ElapsedS 设备 Stream 区间同一或同步 Stream 上的精确起止耗时(如 FPM wall_time)不计入其他并发 Stream 的资源争用
NCCL Profiler PluginS Rank / CollectiveAllReduce / AllGather / SendRecv 起止、Channel / Proxy 活动、多 Rank 到达偏斜需 NCCL 2.23+ 并加载插件;导出为 Trace,不是默认 Prometheus 指标
§ 09RDMA & Storage Backend

网络与存储后端:
当软件层说“传输慢”,硬件发生了什么

软件层的传输耗时仅能说明存在停顿,无法解释停顿根因。下钻到物理网卡与驱动计数器,才能精准定性链路拥塞、丢包重传、接收缓冲耗尽或对端挂起。

FIG 17 / 一次 RDMA 写入经过的硬件观测点 悬停查看计数器含义
发送停顿 port_xmit_wait 指当下游流控反压 接收告警 out_of_buffer / rnr 指对端缓冲耗尽

RDMA 传输抖动的根因可能沿途分布在发送队列、交换机缓冲或对端 WQE 深度。定位不能只关注吞吐速率:port_xmit_wait 标识发送侧受阻(如流控反压),而 out_of_buffer 与 rnr_nak_retry_err 则是接收侧未能及时挂入缓冲的信号,两者的归因与处置路径完全相反。

9.1网卡计数器与单位

计数器目录单位物理含义与判读
port_rcv_data / port_xmit_datacounters/C 4-byte words收发累计数据量;原始值以 4 字节 word 为单位,换算字节需乘 4
port_xmit_waitcounters/C ticks因 PFC Pause 或 IB Credit 不足导致发送停顿;增量飙升指向下游拥塞
np_cnp_sent / rp_cnp_handledhw_counters/C 包RoCEv2 DCQCN:发出与处理 CNP 的次数
roce_adp_retrans / duplicate_requesthw_counters/C 次自适应重传与重复请求;大于 0 直接证明丢包或乱序
rnr_nak_retry_errhw_counters/C 次Receiver Not Ready 重试耗尽;接收端未及时挂入 Recv WQE 或内存不足
local_ack_timeout_errhw_counters/C 次等待 ACK 超时;交换机丢包、光纤闪断或对端假死
out_of_bufferhw_counters/C 次接收侧 FIFO 溢出丢包;常见于 PCIe 拥塞或 Host 内存带宽饱和
单位换算

直接读取 sysfs 的 port_rcv_data 时,必须先乘 4 才是字节数。 node_exporter 的 node_infiniband_port_data_received_bytes_total 已完成换算, 直接对 bytes 求 rate() 即可。两种来源混用会得到 4 倍偏差。

9.2从“传输慢”到具体原因的检查顺序

Step 01
传输粒度
对比 nixl_bytes_transferred 与描述符数量。总字节小但描述符多,往往是内存碎片导致大量小包 Scatter-Gather。
Step 02
阻塞方向
port_xmit_wait 飙升指向发送端受阻;out_of_buffer 与 rnr_nak_retry_err 则指示对端接收缓冲耗尽。
Step 03
链路质量
roce_adp_retrans 与 local_ack_timeout_err 递增代表物理链路丢包、光模块闪断或对端宕机。
Step 04
流控状态
np_cnp_sent 激增说明已触发拥塞通知,需检查交换机队列水位与 PFC/ECN 阈值匹配。

9.3Mooncake:控制面与数据面分开看

FIG 18 / Mooncake 的两条路径 延迟单位:μs / ms
控制面 元数据路由与租约 RPC 数据面 点对点 RDMA 传输与本地 SSD 换入

mooncake_client_rpc_latency 仅度量客户端与 Master 节点间的控制元数据交互,不能代表实际数据搬运耗时。实际传输表现需观察 mooncake_transfer_get_latency 与 SSD I/O 指标;此外,单 Key 操作与 Batch 操作的数据体量差异悬殊,看板中必须按操作类型独立聚合。

指标平面单位判读
mooncake_transfer_read_bytes / write_bytes数据面C bytes名字无 _total,但为单调 Counter,用 rate() 求吞吐
mooncake_transfer_get_latency / put_latency数据面H μs单 key 操作;单位是微秒
mooncake_transfer_batch_get_latency / batch_put_latency数据面H μs批量操作,数据量远大于单 key,必须单独看板
mooncake_client_rpc_count / rpc_latency控制面C 次 / H μsClient → Master 的元数据 RPC;不是数据搬运耗时
mooncake_ssd_read_latency_us / write_latency_usSSDH μs与传输延迟可能嵌套包含,不可直接相加
mooncake_process_rss_bytes / swap_bytes进程G bytesSwap 大于 0 会让微秒级 RDMA / RPC 退化为毫秒级长尾
mooncake_master_allocated_bytes / total_capacity_bytesMasterG bytes全局分配与总容量;含多租户配额水位
mooncake_master_eviction_failed_totalMasterC 次所有副本均处于租约锁定,无法淘汰释放空间
mooncake_master_snapshot_duration_ms / snapshot_restore_fail_totalMaster HAH ms / C 次快照耗时过长会阻塞控制面 RPC
端点区分

Master 的 GET :9003/metrics 是标准 Prometheus 文本格式; GET :9003/metrics/summary 是单行人类可读摘要,不能配置进 Scrape Job。 Store Client 端点(默认 :9300)需要 MC_STORE_CLIENT_METRIC=1 才启用。 Transfer Engine 的 MC_TE_METRIC=1 打印周期性日志统计,但新一代 TENT 引擎不支持该开关。

§ 10Evidence Chain

排障证据链:
先看什么,再对照什么,哪里必须停

按异常表象组织排查链路:先看第一响应指标,再交叉印证底层证据,并厘清推论成立的前提边界。

10.1核心观测集

全量指标会带来额外的高基数存储与抓取开销。覆盖主链路的最简指标组合如下,各层保留关键指标用于快速定界与证伪:

层最小集合它能证伪什么通常需要的开关
入口dynamo_frontend_time_to_first_token_seconds、dynamo_router_overhead_seconds、dynamo_frontend_queued_requests“引擎慢”其实发生在网关排队或路由网关 / Dynamo 默认
引擎time_to_first_token_seconds、inter_token_latency_seconds、request_queue_time_seconds、num_requests_waiting延迟是排队、Prefill 还是 Decode 引起vLLM / SGLang 默认
KVkv_cache_usage_perc、num_preemptions、num_requests_waiting_by_reason高水位是否已经导致驱逐重算vLLM 默认;block 级需 --kv-cache-metrics
缓存 / PDkv_transfer_latency_ms、num_decode_prealloc_queue_reqs、prefetched_tokens_total跨节点交接或分层回载是否成为瓶颈PD / HiCache / Connector 开启后
GPUGPU_UTIL、SM_ACTIVE、PIPE_TENSOR_ACTIVE、DRAM_ACTIVE、FB_USED“卡忙”是否等于“算力被用满”DCGM;SM / NVLink 需自定义 CSV
网络port_xmit_wait、roce_adp_retrans、rnr_nak_retry_err传输慢是否来自链路或接收端node_exporter / rdma_exporter
§ 11PromQL & Statistics

PromQL:聚合顺序与统计语义

跨实例分位数必须先按 le 归并直方图分桶,再调用 histogram_quantile()。直接对多实例的 P99 取平均会抹平真实长尾,是监控统计中最隐蔽的误区。

FIG 19 / 平均 P99 与合并 P99 的差别 示意数据 · 两个实例
算术平均误区 直接平均分位数会抹平单机长尾 正确聚合 先合并直方图分桶再计算全局分位

实例 A 与 B 的 P99 分别为 120ms 与 400ms。若先在各实例计算分位再取算术平均,会得出虚假的 260ms;而先合并各桶样本再计算分位数,真实的全局 P99 依然是 400ms。对分位数求平均会掩盖单节点的严重长尾,给容量与 SLA 评估带来误导。

11.1四条聚合规则

Rule 01
先合并桶再取分位
histogram_quantile(q, sum by (le) (rate(..._bucket[5m])))。跨实例与跨容器聚合的通用基准。
Rule 02
主 Rank 过滤去重
张量并行(TP)下,吞吐与计数器指标需限定 tp_rank="0" 或按 dp_rank 归并,避免被卡数成倍放大。
Rule 03
分母设防零保护
命中率在低谷无流量时分母为 0 会返回 NaN,应在分母添加 > 0 或使用 clamp_min()。
Rule 04
同图指标单位归一
SGLang 传输耗时为 ms,Mooncake 为 μs,网卡原始计数为 4-byte word。混合同图前必须统一缩放基准。

11.2可直接使用的查询

模型全局 TTFT P99vLLM
histogram_quantile(0.99, sum by (model_name, le) (rate(vllm:time_to_first_token_seconds_bucket[5m])))
按 model_name 与 le 归并同口径桶后再取分位数,自动合并多实例与不同 priority 的样本。
集群生成吞吐(防止 TP 重复翻倍)vLLM
sum by (model_name) (rate(vllm:generation_tokens_total{tp_rank=~"0|"}[5m]))
过滤 tp_rank=~"0|" 既兼容未打 TP 标签的单卡环境,也避免在多卡张量并行下把吞吐重复累加。
本地前缀缓存 Token 命中率vLLM
sum by (model_name) (rate(vllm:prefix_cache_hits_total[5m])) / (sum by (model_name) (rate(vllm:prefix_cache_queries_total[5m])) > 0)
前缀命中率是 Token 粒度而非请求粒度。分母附加 > 0,确保在无流量时返回空集而非 NaN。
LMCache MP 的 L1 与 L2 分层命中率LMCache
sum(rate(lmcache_mp_lookup_hit_l1_total[5m])) / (sum(rate(lmcache_mp_lookup_requested_total[5m])) > 0)
在 LMCache MP 中,lookup_hit_l2 仅统计 L1 未命中但命中 L2 的样本;总命中率可直接累加两层命中量,但分母始终使用总查询 Key 数。
PD 跨节点传输 P99(统一到秒)SGLang
histogram_quantile(0.99, sum by (model_name, le) (rate(sglang:kv_transfer_latency_ms_bucket[5m]))) / 1000
原生直方图以毫秒计,需除以 1000 换算为秒以便与 TTFT 同图对照;除法必须置于分位数计算之后。
NIXL 实际传输带宽vLLM NIXL
sum by (instance) (rate(vllm:nixl_bytes_transferred_sum[5m])) / 1048576
nixl_bytes_transferred 为直方图,累计字节流量应提取 _sum 后求 rate();除以 1048576 转换为 MiB/s。
Mooncake Client 读取带宽Mooncake
sum by (instance) (rate(mooncake_transfer_read_bytes[5m])) / 1048576
该指标命名虽然缺少 _total 后缀,但底层为单调递增 Counter,需通过 rate() 计算瞬时带宽。
RDMA 物理端口接收带宽node_exporter
sum by (instance, device) (rate(node_infiniband_port_data_received_bytes_total[1m])) / 1e9
node_exporter 已将原始 4 字节 Word 转换为字节;若直接从内核 sysfs 采集,需手动乘以 4。
高基数与标签

vLLM V1 指标可能携带 priority、model_name 等维度。 用 sum by 时显式归并,避免同一指标因为标签组合不同被重复计算。 对于 cache_hit_rate 这类 Gauge,不要跨实例求算术平均:先取各实例的分子分母,再合并计算。

§ 12Sources & Versions

来源与版本:本文结论对应的上游坐标

各框架指标实现与命名演进活跃。下列链接与 Commit 为本文梳理时的核查坐标;生产环境部署前应以对应版本的 /metrics 输出为准。

客户端基准与网关

vLLM

SGLang

KV Cache / LMCache / Mooncake

GPU / 通信 / 统计

12.1核查基准

项目锁定 Commit核查日期
vLLMace90aeb247a757d32fd8e37e02eb60ba8fd0a462026-10-27
SGLange4d4a9a7de5454cd8b854b21af723c2155a55a3d2026-10-27
Mooncakeb03155412e7d41782b24558548b952fd7f2d6ee32026-10-27
架构坐标系

指标命名常随版本迭代更替,但其背后的三维坐标——观察层级(Request / Server)、物理单位(s / ms / μs / bytes / token / block)以及导出形态(Counter / Gauge / Histogram / Span)始终稳定。接入新指标时,先对齐其所在坐标,即可快速明确其在监控体系中的定位。