[Core] Record Event Driven dispatch queue high water

Signed-off-by: Sy03 <1370724210@qq.com>
This commit is contained in:
Sy03 committed 2026-09-16 11:23:36 +08:00
1 parent 521ef843c6
commit b1e10b0235
4 files changed
+32

No files matched your search

+6
View File
@@ -317,6 +317,8 @@ Each 1-second window records:
|---|---|
| `windows.duration_s` | Wall time covered by the window |
| `windows.loop_idle` / `windows.loop_active` | Orchestrator poll-loop iterations with no work vs. active forwarding |
| `windows.dispatch_queue_size` | Ready-queue size sampled at each monitor window boundary |
| `windows.dispatch_queue_high_water` | Maximum Event Driven ready-queue size observed in each window |
| `replicas.<stage,replica>.outputs_queue_size` | MP client `outputs_queue` backlog for that replica |
| `replicas.<stage,replica>.inflight` | Requests currently bound/routed to the replica |
@@ -331,6 +333,10 @@ orchestrator wakes only once per 0.5 s reconcile timeout, while a busy one still
records one iteration per routed output. Window counts and the `loop_active_pct`
summary are therefore not comparable across the two modes.
For Event Driven runs, use `dispatch_queue_high_water` rather than only the
window-boundary `dispatch_queue_size`: a serial dispatcher can drain a burst
before the window closes, hiding a transient ready-queue backlog in the latter.
### Relationship to other diagnostics
This monitor is intentionally separate from the existing profiling tools:
@@ -45,6 +45,8 @@ def test_note_loop_and_flush_json(tmp_path, monkeypatch):
monitor.register_replica(0, 0)
monitor.note_loop(idle=False)
monitor.set_dispatch_queue_size(9)
monitor.set_dispatch_queue_size(7)
monitor.note_loop(idle=True)
now[0] = 1.5
@@ -54,6 +56,8 @@ def test_note_loop_and_flush_json(tmp_path, monkeypatch):
assert payload["configured_window_s"] == monitor_mod._WINDOW_S
assert payload["windows"]["loop_idle"] == [1]
assert payload["windows"]["loop_active"] == [1]
assert payload["windows"]["dispatch_queue_size"] == [7]
assert payload["windows"]["dispatch_queue_high_water"] == [9]
assert payload["replicas"]["stage=0,replica=0"]["outputs_queue_size"] == [5]
assert payload["replicas"]["stage=0,replica=0"]["inflight"] == [10]
+2
View File
@@ -1278,6 +1278,7 @@ class Orchestrator:
await asyncio.sleep(0.001)
continue
await ready_q.put(("llm", stage_id, replica_id, raw_outputs))
self._orch_monitor.set_dispatch_queue_size(ready_q.qsize())
except asyncio.CancelledError:
raise
except BaseException as e: # noqa: BLE001 - routed to the dispatcher
@@ -1296,6 +1297,7 @@ class Orchestrator:
if output is None:
continue
await ready_q.put(("diffusion", stage_id, replica_id, output))
self._orch_monitor.set_dispatch_queue_size(ready_q.qsize())
got = True
await asyncio.sleep(0 if got else 0.001)
except asyncio.CancelledError:
+20
View File
@@ -56,6 +56,8 @@ class OrchestratorMonitorBase(Protocol):
def note_loop(self, *, idle: bool) -> None: ...
def set_dispatch_queue_size(self, size: int) -> None: ...
def flush(self) -> None: ...
@@ -66,6 +68,9 @@ class _NullOrchestratorMonitor:
def note_loop(self, *, idle: bool) -> None:
return
def set_dispatch_queue_size(self, size: int) -> None:
return
def flush(self) -> None:
return
@@ -94,6 +99,10 @@ class OrchestratorMonitor:
self._duration_s: list[float] = []
self._loop_idle_buf: list[int] = []
self._loop_active_buf: list[int] = []
self._dispatch_queue_size = 0
self._dispatch_queue_size_buf: list[int] = []
self._dispatch_queue_high_water = 0
self._dispatch_queue_high_water_buf: list[int] = []
self._replicas: dict[str, _ReplicaSeries] = {}
def register_replica(self, stage_id: int, replica_id: int) -> None:
@@ -107,6 +116,11 @@ class OrchestratorMonitor:
else:
self._loop_active += 1
def set_dispatch_queue_size(self, size: int) -> None:
size = max(int(size), 0)
self._dispatch_queue_size = size
self._dispatch_queue_high_water = max(self._dispatch_queue_high_water, size)
def flush(self) -> None:
if self._flushed:
return
@@ -118,6 +132,8 @@ class OrchestratorMonitor:
"duration_s": self._duration_s,
"loop_idle": self._loop_idle_buf,
"loop_active": self._loop_active_buf,
"dispatch_queue_size": self._dispatch_queue_size_buf,
"dispatch_queue_high_water": self._dispatch_queue_high_water_buf,
},
"replicas": dict(sorted(self._replicas.items())),
}
@@ -154,6 +170,8 @@ class OrchestratorMonitor:
self._duration_s.append(max(now_mono - self._window_start_mono, 1e-9))
self._loop_idle_buf.append(self._loop_idle)
self._loop_active_buf.append(self._loop_active)
self._dispatch_queue_size_buf.append(self._dispatch_queue_size)
self._dispatch_queue_high_water_buf.append(self._dispatch_queue_high_water)
for key, series in self._replicas.items():
outputs_qsize, inflight = sampled.get(key, (0, 0))
series["outputs_queue_size"].append(outputs_qsize)
@@ -161,6 +179,8 @@ class OrchestratorMonitor:
self._loop_idle = 0
self._loop_active = 0
self._dispatch_queue_size = 0
self._dispatch_queue_high_water = 0
self._window_start_mono = now_mono
def _log_summary(self, output_path: str) -> None: