@@ -275,10 +275,26 @@ def get_config(self):
275275
276276
277277def _install_stubs ():
278+ _install_module (
279+ "numpy" ,
280+ ndarray = object ,
281+ bool_ = bool ,
282+ uint64 = "uint64" ,
283+ int64 = "int64" ,
284+ zeros = lambda shape , * args , ** kwargs : [
285+ [0 for _ in range (shape [1 ])] for _ in range (shape [0 ])
286+ ],
287+ vstack = lambda rows : list (rows ),
288+ concatenate = lambda arrays , axis = 0 : [
289+ item for array in arrays for item in list (array )
290+ ],
291+ asarray = lambda values , dtype = None : values ,
292+ arange = lambda * args , ** kwargs : list (range (* args )),
293+ isscalar = lambda value : isinstance (value , (int , float , bool , str , bytes )),
294+ )
278295 _install_package ("ucm" , REPO_ROOT / "ucm" )
279296 _install_package ("ucm.integration" , REPO_ROOT / "ucm" / "integration" )
280297 _install_package ("ucm.integration.vllm" , REPO_ROOT / "ucm" / "integration" / "vllm" )
281- _install_module ("numpy" , ndarray = type ("ndarray" , (), {}))
282298 _install_module ("torch" , Tensor = type ("Tensor" , (), {}))
283299 _install_module (
284300 "prometheus_client" ,
@@ -354,7 +370,13 @@ def _install_stubs():
354370
355371_install_stubs ()
356372
373+ import ucm .integration .vllm .hma_connector as hma_connector_module
357374import ucm .integration .vllm .ucm_connector as ucm_connector_module
375+ from ucm .integration .vllm .hma_connector import (
376+ FAWARequestDispatchMeta ,
377+ UCMFAWAConnector ,
378+ UCMFAWAConnectorMetadata ,
379+ )
358380from ucm .integration .vllm .metrics import UCMConnectorStats , UCMPromMetrics
359381from ucm .integration .vllm .ucm_connector import (
360382 PendingDumpTask ,
@@ -460,6 +482,38 @@ def _reset_fakes():
460482 dispatcher_module ._DISPATCHER = None
461483
462484
485+ class FakeHMAStore :
486+ def __init__ (self , label , fail_wait = False ):
487+ self .label = label
488+ self .fail_wait = fail_wait
489+ self .loaded = []
490+ self .dumped = []
491+ self .waited = []
492+
493+ def load_data (self , keys , shard_indices , ptrs ):
494+ task = f"{ self .label } -load-{ len (keys )} -{ len (self .loaded )} "
495+ self .loaded .append ((list (keys ), list (shard_indices ), ptrs , task ))
496+ return task
497+
498+ def dump_data (self , keys , shard_indices , ptrs , event_handle ):
499+ task = f"{ self .label } -dump-{ len (keys )} -{ len (self .dumped )} "
500+ self .dumped .append ((list (keys ), list (shard_indices ), ptrs , event_handle , task ))
501+ return task
502+
503+ def wait (self , task ):
504+ self .waited .append (task )
505+ if self .fail_wait :
506+ raise RuntimeError (f"{ self .label } wait failed" )
507+
508+
509+ class FakeHMADevice :
510+ def __init__ (self ):
511+ self .destroyed = []
512+
513+ def destroy_event_handle (self , event_handle ):
514+ self .destroyed .append (event_handle )
515+
516+
463517def test_config_definitions_register_enable_list_and_metric_names ():
464518 _reset_fakes ()
465519 config = _metrics_config ()
@@ -969,6 +1023,212 @@ def destroy_event_handle(self, event_handle):
9691023 ]
9701024
9711025
1026+ def _fawa_request (load_keys = None , dump_keys = None ):
1027+ return FAWARequestDispatchMeta (
1028+ load_keys = list (load_keys or []),
1029+ load_hash_start = 0 ,
1030+ load_hash_end = len (load_keys or []),
1031+ load_vllm_block_ids = ([1 , 2 ],),
1032+ dump_keys = list (dump_keys or []),
1033+ dump_hash_start = 0 ,
1034+ dump_hash_end = len (dump_keys or []),
1035+ dump_vllm_block_ids = ([1 , 2 ],),
1036+ )
1037+
1038+
1039+ def _new_hma_connector (metadata , fa_store = None , wa_store = None ):
1040+ connector = object .__new__ (UCMFAWAConnector )
1041+ connector .fa_store = fa_store or FakeHMAStore ("FA" )
1042+ connector .wa_store = wa_store or FakeHMAStore ("WA" )
1043+ connector ._fawa_store_block_sizes = {"FA" : 100 , "WA" : 20 }
1044+ connector ._invalid_block_ids = set ()
1045+ connector .tp_size = 1
1046+ connector .tp_rank = 0
1047+ connector .wa_dump_block_wise = True
1048+ connector .fa_group_ids = set ()
1049+ connector .window_group_ids = set ()
1050+ connector .group_metas = []
1051+ connector .tp_dump_tasks = {}
1052+ connector ._fawa_dump_group_metrics = {}
1053+ connector ._fawa_next_dump_group_id = 0
1054+ connector ._direct_task_has_load = False
1055+ connector ._direct_task_load_duration_ms = 0.0
1056+ connector ._direct_task_compute_start_ms = None
1057+ connector .device = FakeHMADevice ()
1058+ connector ._get_connector_metadata = lambda : metadata
1059+ connector ._extract_fa_ptr = lambda * args , ** kwargs : [[0 ], [0 ]]
1060+ connector ._extract_wa_ptr = lambda * args , ** kwargs : [[0 ], [0 ]]
1061+ return connector
1062+
1063+
1064+ def test_hma_connector_records_load_metrics (monkeypatch ):
1065+ _reset_fakes ()
1066+ times = iter ([1.0 , 1.1 , 1.11 ])
1067+ monkeypatch .setattr (
1068+ hma_connector_module .time ,
1069+ "perf_counter" ,
1070+ lambda : next (times ),
1071+ )
1072+ metadata = UCMFAWAConnectorMetadata (
1073+ request_meta = {"req-1" : _fawa_request (load_keys = [b"a" , b"b" ])}
1074+ )
1075+ connector = _new_hma_connector (metadata )
1076+
1077+ connector .start_load_kv (None )
1078+
1079+ stats = fake_ucmmetrics .updated [- 1 ]
1080+ assert stats ["load_requests_num" ] == 1
1081+ assert stats ["load_blocks_num" ] == 3
1082+ assert stats ["load_duration" ] == pytest .approx (100.0 )
1083+ assert stats ["load_bytes_total" ] == 220
1084+ assert stats ["load_speed" ] == pytest .approx (220 / 100 / 1024 / 1024 )
1085+ assert connector ._direct_task_has_load is True
1086+ assert connector ._direct_task_load_duration_ms == pytest .approx (100.0 )
1087+ assert connector ._direct_task_compute_start_ms == pytest .approx (1110.0 )
1088+
1089+
1090+ def test_hma_connector_load_metrics_ignore_wait_failure_for_counting (monkeypatch ):
1091+ _reset_fakes ()
1092+ times = iter ([1.0 , 1.1 , 1.11 ])
1093+ monkeypatch .setattr (
1094+ hma_connector_module .time ,
1095+ "perf_counter" ,
1096+ lambda : next (times ),
1097+ )
1098+ metadata = UCMFAWAConnectorMetadata (
1099+ request_meta = {"req-1" : _fawa_request (load_keys = [b"a" , b"b" ])}
1100+ )
1101+ connector = _new_hma_connector (metadata , wa_store = FakeHMAStore ("WA" , True ))
1102+
1103+ connector .start_load_kv (None )
1104+
1105+ stats = fake_ucmmetrics .updated [- 1 ]
1106+ assert stats ["load_requests_num" ] == 1
1107+ assert stats ["load_blocks_num" ] == 3
1108+ assert stats ["load_bytes_total" ] == 220
1109+ assert stats ["load_speed" ] == pytest .approx (220 / 100 / 1024 / 1024 )
1110+ assert connector ._invalid_block_ids == {1 , 2 }
1111+
1112+
1113+ @pytest .mark .parametrize ("drain_method" , ["get_finished" , "preemption" ])
1114+ def test_hma_connector_records_grouped_save_completion_metrics (
1115+ monkeypatch , drain_method
1116+ ):
1117+ _reset_fakes ()
1118+ times = iter ([1.0 , 1.01 , 1.02 , 1.10 , 1.12 , 1.13 , 1.15 ])
1119+ monkeypatch .setattr (
1120+ hma_connector_module .time ,
1121+ "perf_counter" ,
1122+ lambda : next (times ),
1123+ )
1124+ metadata = UCMFAWAConnectorMetadata (
1125+ request_meta = {"req-1" : _fawa_request (dump_keys = [b"a" , b"b" ])}
1126+ )
1127+ connector = _new_hma_connector (metadata )
1128+ handles = iter ([11 , 12 ])
1129+ connector ._get_dump_event_handle = lambda : next (handles )
1130+ connector ._direct_task_has_load = True
1131+ connector ._direct_task_load_duration_ms = 10.0
1132+ connector ._direct_task_compute_start_ms = 900.0
1133+
1134+ connector .wait_for_save ()
1135+
1136+ assert fake_ucmmetrics .updated == [
1137+ {
1138+ "save_requests_num" : 1 ,
1139+ "save_blocks_num" : 4 ,
1140+ "save_bytes_total" : 240 ,
1141+ }
1142+ ]
1143+ if drain_method == "get_finished" :
1144+ connector .get_finished ({"req-1" })
1145+ else :
1146+ connector .handle_preemptions (
1147+ UCMFAWAConnectorMetadata (preempted_req_ids = {"req-1" })
1148+ )
1149+
1150+ completion_stats = fake_ucmmetrics .updated [- 2 ]
1151+ assert completion_stats ["save_duration" ] == pytest .approx (140.0 )
1152+ assert completion_stats ["save_speed" ] == pytest .approx (240 / 140 / 1024 / 1024 )
1153+ assert completion_stats ["save_completion_wait_duration" ] == pytest .approx (50.0 )
1154+ assert completion_stats ["save_completion_wait_speed" ] == pytest .approx (
1155+ 240 / 50 / 1024 / 1024
1156+ )
1157+ task_stats = fake_ucmmetrics .updated [- 1 ]
1158+ assert task_stats ["connector_task_load_stage_load_dump_ms" ] == 10.0
1159+ assert task_stats ["connector_task_compute_stage_load_dump_ms" ] == pytest .approx (
1160+ 100.0
1161+ )
1162+ assert task_stats ["connector_task_dump_stage_load_dump_ms" ] == pytest .approx (140.0 )
1163+ assert task_stats ["connector_task_total_load_dump_ms" ] == pytest .approx (250.0 )
1164+ assert connector .device .destroyed == [11 , 12 ]
1165+ assert connector .tp_dump_tasks == {}
1166+ assert connector ._fawa_dump_group_metrics == {}
1167+
1168+
1169+ def test_hma_connector_save_metrics_count_only_submitted_requests_without_changing_tp_keys (
1170+ monkeypatch ,
1171+ ):
1172+ _reset_fakes ()
1173+ times = iter ([1.0 , 1.01 , 1.02 ])
1174+ monkeypatch .setattr (
1175+ hma_connector_module .time ,
1176+ "perf_counter" ,
1177+ lambda : next (times ),
1178+ )
1179+ metadata = UCMFAWAConnectorMetadata (
1180+ request_meta = {
1181+ "req-no-rank-work" : _fawa_request (dump_keys = [b"a" ]),
1182+ "req-rank-work" : _fawa_request (dump_keys = [b"b" , b"c" ]),
1183+ }
1184+ )
1185+ connector = _new_hma_connector (metadata )
1186+ connector .tp_size = 2
1187+ connector .tp_rank = 0
1188+ handles = iter ([11 , 12 ])
1189+ connector ._get_dump_event_handle = lambda : next (handles )
1190+
1191+ connector .wait_for_save ()
1192+
1193+ assert list (connector .tp_dump_tasks ) == [("req-no-rank-work" , "req-rank-work" )]
1194+ assert fake_ucmmetrics .updated == [
1195+ {
1196+ "save_requests_num" : 1 ,
1197+ "save_blocks_num" : 2 ,
1198+ "save_bytes_total" : 120 ,
1199+ }
1200+ ]
1201+
1202+
1203+ def test_hma_connector_no_dump_records_load_only_breakdown (monkeypatch ):
1204+ _reset_fakes ()
1205+ times = iter ([1.0 ])
1206+ monkeypatch .setattr (
1207+ hma_connector_module .time ,
1208+ "perf_counter" ,
1209+ lambda : next (times ),
1210+ )
1211+ metadata = UCMFAWAConnectorMetadata (
1212+ request_meta = {"req-1" : _fawa_request (load_keys = [b"a" ])}
1213+ )
1214+ connector = _new_hma_connector (metadata )
1215+ connector ._direct_task_has_load = True
1216+ connector ._direct_task_load_duration_ms = 7.0
1217+ connector ._direct_task_compute_start_ms = 900.0
1218+
1219+ connector .wait_for_save ()
1220+
1221+ task_stats = fake_ucmmetrics .updated [- 1 ]
1222+ assert task_stats ["connector_task_load_stage_load_only_ms" ] == 7.0
1223+ assert task_stats ["connector_task_compute_stage_load_only_ms" ] == pytest .approx (
1224+ 100.0
1225+ )
1226+ assert task_stats ["connector_task_total_load_only_ms" ] == pytest .approx (107.0 )
1227+ assert connector ._direct_task_has_load is False
1228+ assert connector ._direct_task_load_duration_ms == 0.0
1229+ assert connector ._direct_task_compute_start_ms is None
1230+
1231+
9721232def test_multiproc_logger_uses_prefix_and_dispatcher_snapshot (tmp_path ):
9731233 _reset_fakes ()
9741234 import ucm .observability as observability
0 commit comments