Files
vllm-omni/tests/metrics/test_stats.py
T
Junhong LiuandHongsheng Liu 9af6fb9a1f [Feature] Opt metrics structure (#891)
Signed-off-by: Junhong Liu <98734602+LJH-LBJ@users.noreply.github.com>
Signed-off-by: Junhong Liu <ljh_lbj@163.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-02-09 19:17:32 +08:00

158 lines
4.8 KiB
Python

from __future__ import annotations
import pytest
from vllm_omni.metrics import OrchestratorAggregator
from vllm_omni.metrics.stats import RequestE2EStats, StageRequestStats, StageStats
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
def _get_request_entry(table: list[dict], request_id: str) -> dict:
for entry in table:
if entry.get("request_id") == request_id:
return entry
raise AssertionError(f"request_id={request_id} not found")
def test_orchestrator_aggregator_builds_summary() -> None:
agg = OrchestratorAggregator(num_stages=2, log_stats=True, wall_start_ts=0.0, final_stage_id_for_e2e=1)
agg.stage_first_ts[0] = 0.0
agg.stage_last_ts[0] = 0.03
agg.stage_first_ts[1] = 0.05
agg.stage_last_ts[1] = 0.07
agg.on_forward(0, 1, "r1", size_bytes=1024, tx_ms=5.0, used_shm=False)
agg.on_stage_metrics(
0,
"r1",
StageRequestStats(
batch_id=1,
batch_size=1,
num_tokens_in=3,
num_tokens_out=3,
stage_gen_time_ms=30.0,
rx_transfer_bytes=0,
rx_decode_time_ms=0.0,
rx_in_flight_time_ms=0.0,
stage_stats=StageStats(),
),
)
agg.on_stage_metrics(
1,
"r1",
StageRequestStats(
batch_id=1,
batch_size=1,
num_tokens_in=0,
num_tokens_out=4,
stage_gen_time_ms=20.0,
rx_transfer_bytes=1024,
rx_decode_time_ms=5.0,
rx_in_flight_time_ms=2.0,
stage_stats=StageStats(),
),
)
agg.on_finalize_request(1, "r1", req_start_ts=0.0)
summary = agg.build_and_log_summary()
overall = summary["overall_summary"]
assert overall["e2e_requests"] == 1
stage_entry = _get_request_entry(summary["stage_table"], "r1")
stage_ids = [row["stage_id"] for row in stage_entry["stages"]]
assert stage_ids == [0, 1]
transfer_entry = _get_request_entry(summary["trans_table"], "r1")
assert transfer_entry["transfers"][0]["edge"] == "0->1"
assert transfer_entry["transfers"][0]["size_kbytes"] == 1.0
e2e_entry = _get_request_entry(summary["e2e_table"], "r1")
assert e2e_entry["e2e_total_tokens"] == 10
def test_build_and_log_summary_e2e_only() -> None:
agg = OrchestratorAggregator(num_stages=1, log_stats=True, wall_start_ts=0.0, final_stage_id_for_e2e=0)
agg.e2e_events.append(
RequestE2EStats(
request_id="r",
e2e_total_ms=10.0,
e2e_total_tokens=5,
transfers_total_time_ms=0.0,
transfers_total_bytes=0,
)
)
summary = agg.build_and_log_summary()
e2e_entry = _get_request_entry(summary["e2e_table"], "r")
assert e2e_entry["e2e_total_tokens"] == 5
stage_entry = _get_request_entry(summary["stage_table"], "r")
assert stage_entry["stages"] == []
def test_build_and_log_summary_multiple_requests() -> None:
agg = OrchestratorAggregator(
num_stages=2, log_stats=True, wall_start_ts=0.0, final_stage_id_for_e2e={"r1": 1, "r2": 0}
)
# Request r1 goes through both stages
agg.on_stage_metrics(
0,
"r1",
StageRequestStats(
batch_id=1,
batch_size=1,
num_tokens_in=2,
num_tokens_out=4,
stage_gen_time_ms=10.0,
rx_transfer_bytes=0,
rx_decode_time_ms=0.0,
rx_in_flight_time_ms=0.0,
stage_stats=StageStats(),
),
)
agg.on_stage_metrics(
1,
"r1",
StageRequestStats(
batch_id=1,
batch_size=1,
num_tokens_in=4,
num_tokens_out=5,
stage_gen_time_ms=8.0,
rx_transfer_bytes=0,
rx_decode_time_ms=0.0,
rx_in_flight_time_ms=0.0,
stage_stats=StageStats(),
),
)
agg.on_finalize_request(1, "r1", req_start_ts=0.0)
# Request r2 only goes through stage 0
agg.on_stage_metrics(
0,
"r2",
StageRequestStats(
batch_id=2,
batch_size=1,
num_tokens_in=1,
num_tokens_out=2,
stage_gen_time_ms=12.0,
rx_transfer_bytes=0,
rx_decode_time_ms=0.0,
rx_in_flight_time_ms=0.0,
stage_stats=StageStats(),
),
)
agg.on_finalize_request(0, "r2", req_start_ts=0.0)
summary = agg.build_and_log_summary()
assert len(summary["stage_table"]) == 2
assert {entry["request_id"] for entry in summary["e2e_table"]} == {"r1", "r2"}
# Check that r1 has two stages and r2 has one
r1_stage_entry = next(e for e in summary["stage_table"] if e["request_id"] == "r1")
r2_stage_entry = next(e for e in summary["stage_table"] if e["request_id"] == "r2")
assert len(r1_stage_entry["stages"]) == 2
assert len(r2_stage_entry["stages"]) == 1