Tiny extract SchedulerWatchdog (#15021)

This commit is contained in:
fzyzcjy
2025-12-13 10:40:32 +08:00
committed by GitHub
parent df111bc0fe
commit 487cf81a68
2 changed files with 37 additions and 21 deletions
+4 -5
View File
@@ -18,7 +18,6 @@ import logging
import os import os
import signal import signal
import sys import sys
import threading
import time import time
from collections import deque from collections import deque
from concurrent import futures from concurrent import futures
@@ -146,6 +145,7 @@ from sglang.srt.managers.scheduler_profiler_mixin import SchedulerProfilerMixin
from sglang.srt.managers.scheduler_recv_skipper import SchedulerRecvSkipper from sglang.srt.managers.scheduler_recv_skipper import SchedulerRecvSkipper
from sglang.srt.managers.scheduler_runtime_checker_mixin import ( from sglang.srt.managers.scheduler_runtime_checker_mixin import (
SchedulerRuntimeCheckerMixin, SchedulerRuntimeCheckerMixin,
SchedulerWatchdog,
) )
from sglang.srt.managers.scheduler_update_weights_mixin import ( from sglang.srt.managers.scheduler_update_weights_mixin import (
SchedulerUpdateWeightsMixin, SchedulerUpdateWeightsMixin,
@@ -524,10 +524,9 @@ class Scheduler(
self.new_token_ratio = self.init_new_token_ratio self.new_token_ratio = self.init_new_token_ratio
# Init watchdog thread # Init watchdog thread
self.watchdog_timeout = server_args.watchdog_timeout self.watchdog = SchedulerWatchdog(
t = threading.Thread(target=self.watchdog_thread, daemon=True) self, watchdog_timeout=server_args.watchdog_timeout
t.start() )
self.parent_process = psutil.Process().parent()
# Init memory saver, profiler and metric stats # Init memory saver, profiler and metric stats
self.memory_saver_adapter = TorchMemorySaverAdapter.create( self.memory_saver_adapter = TorchMemorySaverAdapter.create(
@@ -3,9 +3,12 @@ from __future__ import annotations
import logging import logging
import signal import signal
import sys import sys
import threading
import time import time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import psutil
from sglang.srt.disaggregation.utils import DisaggregationMode from sglang.srt.disaggregation.utils import DisaggregationMode
from sglang.srt.environ import envs from sglang.srt.environ import envs
from sglang.srt.managers.schedule_batch import ScheduleBatch from sglang.srt.managers.schedule_batch import ScheduleBatch
@@ -302,33 +305,47 @@ class SchedulerRuntimeCheckerMixin:
self.new_token_ratio = self.init_new_token_ratio self.new_token_ratio = self.init_new_token_ratio
self.maybe_sleep_on_idle() self.maybe_sleep_on_idle()
def watchdog_thread(self: Scheduler):
"""A watch dog thread that will try to kill the server itself if one forward batch takes too long.""" class SchedulerWatchdog:
self.watchdog_last_forward_ct = 0 """A watch dog that will try to kill the server itself if one forward batch takes too long."""
self.watchdog_last_time = time.perf_counter()
def __init__(self, scheduler: Scheduler, watchdog_timeout: float):
self.scheduler = scheduler
self.watchdog_timeout = watchdog_timeout
t = threading.Thread(target=self._watchdog_thread, daemon=True)
t.start()
self.parent_process = psutil.Process().parent()
def _watchdog_thread(self):
watchdog_last_forward_ct = 0
watchdog_last_time = time.perf_counter()
while True: while True:
current = time.perf_counter() current = time.perf_counter()
if self.cur_batch is not None: if self.scheduler.cur_batch is not None:
if self.watchdog_last_forward_ct == self.forward_ct: if watchdog_last_forward_ct == self.scheduler.forward_ct:
if current > self.watchdog_last_time + self.watchdog_timeout: if current > watchdog_last_time + self.watchdog_timeout:
break break
else: else:
self.watchdog_last_forward_ct = self.forward_ct watchdog_last_forward_ct = self.scheduler.forward_ct
self.watchdog_last_time = current watchdog_last_time = current
time.sleep(self.watchdog_timeout // 2) time.sleep(self.watchdog_timeout // 2)
if not disable_request_logging(): if not disable_request_logging():
# TODO extract this duplicated logic w/ another place
# Print batch size and memory pool info to check whether there are de-sync issues. # Print batch size and memory pool info to check whether there are de-sync issues.
if self.is_hybrid_swa: if self.scheduler.is_hybrid_swa:
_, info_msg = self._check_hybrid_memory() _, info_msg = self.scheduler._check_hybrid_memory()
elif self.is_ssm_model and isinstance(self.tree_cache, MambaRadixCache): elif self.scheduler.is_ssm_model and isinstance(
_, info_msg = self._check_mamba_memory() self.scheduler.tree_cache, MambaRadixCache
):
_, info_msg = self.scheduler._check_mamba_memory()
else: else:
_, info_msg = self._check_radix_cache_memory() _, info_msg = self.scheduler._check_radix_cache_memory()
logger.error( logger.error(
f"{self.cur_batch.batch_size()=}\n" f"{self.scheduler.cur_batch.batch_size()=}\n"
f"{self.cur_batch.reqs=}\n" f"{self.scheduler.cur_batch.reqs=}\n"
f"{info_msg}" f"{info_msg}"
) )