From afc91fa0d2eb8bc050d80e9bcd74c8b1d72b4191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elvir=20Crn=C4=8Devi=C4=87?= Date: Tue, 25 Aug 2026 14:13:29 +0200 Subject: [PATCH] [Profiler] Fix start_profile permanently no-op after max_iterations auto-stop (#51839) Signed-off-by: Elvir Crncevic --- tests/v1/worker/test_gpu_profiler.py | 28 ++++++++++++++++++++++++++++ vllm/profiler/wrapper.py | 10 ++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/tests/v1/worker/test_gpu_profiler.py b/tests/v1/worker/test_gpu_profiler.py index 3e236a73b1..347b5b379a 100644 --- a/tests/v1/worker/test_gpu_profiler.py +++ b/tests/v1/worker/test_gpu_profiler.py @@ -112,6 +112,34 @@ def test_max_iterations(default_profiler_config): # Should have stopped now assert profiler._running is False assert profiler.stop_call_count == 1 + # And fully reset, not just paused -- a later start_profile must not be a + # permanent no-op just because max_iterations already fired once. + assert profiler._active is False + assert profiler._active_iteration_count == 0 + assert profiler._profiling_for_iters == 0 + + +def test_restart_after_max_iterations(default_profiler_config): + """A start_profile after an auto-stop must actually restart, not be + silently ignored (regression test: auto-stop used to leave _active + True forever, so start() always bailed out early).""" + default_profiler_config.max_iterations = 2 + profiler = ConcreteWorkerProfiler(default_profiler_config) + + profiler.start() + profiler.step() + profiler.step() + profiler.step() # exceeds max, auto-stops + assert profiler._running is False + assert profiler.start_call_count == 1 + + profiler.start() + assert profiler._active is True + assert profiler._running is True + assert profiler.start_call_count == 2 + + profiler.step() + assert profiler._running is True def test_delayed_start_and_max_iters(default_profiler_config): diff --git a/vllm/profiler/wrapper.py b/vllm/profiler/wrapper.py index 2f56d0fc7c..877a390d6d 100644 --- a/vllm/profiler/wrapper.py +++ b/vllm/profiler/wrapper.py @@ -120,11 +120,13 @@ class WorkerProfiler(ABC): and self._running and self._profiling_for_iters > self._max_iters ): - # Automatically stop the profiler after max iters - # will be marked as not running, but leave as active so that stop - # can clean up properly + # Automatically stop the profiler after max iters. Go through the + # public stop() (not _call_stop() directly) so _active and the + # iteration counters reset too -- otherwise a later start_profile + # is silently ignored forever, since start() bails out early + # whenever _active is still True. logger.info_once("Max profiling iterations reached. Stopping profiler...") - self._call_stop() + self.stop() return def _profiler_step(self) -> bool: