A5 fix: worker-id resolution and vLLM cmpl- rid stripping
Smoke validation on dash0 surfaced three real bugs that broke interference and failure-attribution labels end-to-end: 1. endpoint_url in metrics is the proxy URL (e.g. http://h:9200); the vLLM worker URL lives in breakdown's routed_to. The interference index and label path were taking endpoint_url first, so every request looked routed to a non-existent worker and the overlap counter stayed at zero. 2. _normalize_worker hard-coded base port 8000, so a smoke run on port 9100 resolved to engine_1100 instead of engine_0. Added a --worker-map URL=engine_id CLI flag and _resolve_worker() that prefers the explicit map and falls back to the heuristic. 3. vLLM rewrites the per-step rid as cmpl-<proxy_id>-<i>-<hash>, so the str equality check between per_req rid and our proxy request_id never matched -> every prefill step looked like "other request prefill", which would have flipped overlap to 100%. Added _vllm_rid_matches() that strips the cmpl-/chatcmpl- prefix. After the fix, the same smoke run reports interference_index = 22.9 across 24 overlap / 6 clean requests on a single instance, which is the expected shape for serial dispatch into a cold engine. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,8 @@ from analysis.characterization.joined_analysis import (
|
||||
window_summary,
|
||||
_normalize_worker,
|
||||
_percentile,
|
||||
_resolve_worker,
|
||||
_vllm_rid_matches,
|
||||
)
|
||||
|
||||
|
||||
@@ -70,18 +72,22 @@ def test_normalize_worker_maps_port_to_engine_id():
|
||||
|
||||
def test_interference_index_marks_overlap_when_other_request_prefilling():
|
||||
metrics = [
|
||||
_mk_metric("decode_target", endpoint_url="http://h:8000",
|
||||
_mk_metric("decode_target",
|
||||
t_first_token_unix=10.0, t_finish_unix=11.0,
|
||||
tpot_s=0.10),
|
||||
_mk_metric("decode_clean", endpoint_url="http://h:8001",
|
||||
_mk_metric("decode_clean",
|
||||
t_first_token_unix=20.0, t_finish_unix=21.0,
|
||||
tpot_s=0.04),
|
||||
]
|
||||
joined = build_joined_records(metrics, [], [])
|
||||
breakdown = [
|
||||
{"request_id": "decode_target", "routed_to": "http://h:8000"},
|
||||
{"request_id": "decode_clean", "routed_to": "http://h:8001"},
|
||||
]
|
||||
joined = build_joined_records(metrics, breakdown, [])
|
||||
engine_state = {
|
||||
"engine_0": [
|
||||
{"t_unix": 10.5, "prefill_tokens": 8000,
|
||||
"per_req": [{"rid": "other", "phase": "prefill"}]},
|
||||
"per_req": [{"rid": "cmpl-other-0-aaaa", "phase": "prefill"}]},
|
||||
],
|
||||
"engine_1": [
|
||||
{"t_unix": 20.5, "prefill_tokens": 0,
|
||||
@@ -93,10 +99,22 @@ def test_interference_index_marks_overlap_when_other_request_prefilling():
|
||||
assert out["n_overlap_requests"] == 1
|
||||
assert out["n_clean_requests"] == 1
|
||||
assert out["interference_index"] is not None
|
||||
# Overlap p90 = 0.10; clean p90 = 0.04; ratio > 2
|
||||
assert out["interference_index"] > 2.0
|
||||
|
||||
|
||||
def test_resolve_worker_prefers_explicit_map():
|
||||
assert _resolve_worker("http://h:9100", {"http://h:9100": "engine_0"}) == "engine_0"
|
||||
assert _resolve_worker("http://h:9100", None) == "engine_1100"
|
||||
|
||||
|
||||
def test_vllm_rid_matches_strips_cmpl_prefix():
|
||||
assert _vllm_rid_matches("cmpl-1237198:1:1237198:0-0-b07fed77",
|
||||
"1237198:1:1237198:0")
|
||||
assert _vllm_rid_matches("chatcmpl-abc-0-xx", "abc")
|
||||
assert not _vllm_rid_matches("cmpl-other-0-xx", "1237198:1:1237198:0")
|
||||
assert not _vllm_rid_matches(None, "x")
|
||||
|
||||
|
||||
def test_hotspot_index_max_over_median_p90():
|
||||
"""One hot worker with TTFT 10x the others should drive a >1 index."""
|
||||
rows = []
|
||||
@@ -118,14 +136,10 @@ def test_label_slow_requests_flags_overlap_and_hot_worker():
|
||||
_mk_metric("slow_overlap", ttft_s=10.0,
|
||||
t_first_token_unix=10.0, t_finish_unix=11.0),
|
||||
_mk_metric("slow_no_overlap", ttft_s=10.0,
|
||||
endpoint_url="http://h:8005",
|
||||
t_first_token_unix=20.0, t_finish_unix=21.0),
|
||||
_mk_metric("fast", ttft_s=0.5,
|
||||
t_first_token_unix=15.0, t_finish_unix=16.0),
|
||||
]
|
||||
metrics[0]["routed_to"] = "http://h:8000"
|
||||
metrics[1]["routed_to"] = "http://h:8005"
|
||||
metrics[2]["routed_to"] = "http://h:8000"
|
||||
bk = [
|
||||
{"request_id": "slow_overlap", "routed_to": "http://h:8000"},
|
||||
{"request_id": "slow_no_overlap", "routed_to": "http://h:8005"},
|
||||
@@ -134,7 +148,8 @@ def test_label_slow_requests_flags_overlap_and_hot_worker():
|
||||
joined = build_joined_records(metrics, bk, [])
|
||||
engine_state = {
|
||||
"engine_0": [{"t_unix": 10.5, "prefill_tokens": 5000,
|
||||
"per_req": [{"rid": "other", "phase": "prefill"}]}],
|
||||
"per_req": [{"rid": "cmpl-other-0-x",
|
||||
"phase": "prefill"}]}],
|
||||
}
|
||||
labels = label_slow_requests(joined, engine_state, slow_ttft_factor=2.0)
|
||||
by_id = {L["request_id"]: L["label"] for L in labels}
|
||||
|
||||
Reference in New Issue
Block a user