[Perf] Enable environment cache in EngineCore to enable the feature for UniProcExecutor as well (#29289)

Signed-off-by: Jialin Ouyang <Jialin.Ouyang@gmail.com>
This commit is contained in:
Jialin Ouyang 2025-12-10 11:13:01 -08:00 committed by GitHub
parent e72d65b959
commit 9f042ba26b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 4 deletions

View File

@ -8,6 +8,7 @@ import pytest
import vllm.envs as envs import vllm.envs as envs
from vllm.envs import ( from vllm.envs import (
disable_envs_cache,
enable_envs_cache, enable_envs_cache,
env_list_with_choices, env_list_with_choices,
env_set_with_choices, env_set_with_choices,
@ -57,6 +58,43 @@ def test_getattr_with_cache(monkeypatch: pytest.MonkeyPatch):
envs.__getattr__ = envs.__getattr__.__wrapped__ envs.__getattr__ = envs.__getattr__.__wrapped__
def test_getattr_with_reset(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("VLLM_HOST_IP", "1.1.1.1")
# __getattr__ is not decorated with functools.cache
assert not hasattr(envs.__getattr__, "cache_info")
# Enable envs cache and ignore ongoing environment changes
enable_envs_cache()
assert envs.VLLM_HOST_IP == "1.1.1.1"
# With cache enabled, the environment variable value is cached and unchanged
monkeypatch.setenv("VLLM_HOST_IP", "2.2.2.2")
assert envs.VLLM_HOST_IP == "1.1.1.1"
disable_envs_cache()
assert envs.VLLM_HOST_IP == "2.2.2.2"
# After cache disabled, the environment variable value would be synced
# with os.environ
monkeypatch.setenv("VLLM_HOST_IP", "3.3.3.3")
assert envs.VLLM_HOST_IP == "3.3.3.3"
def test_is_envs_cache_enabled() -> None:
assert not envs._is_envs_cache_enabled()
enable_envs_cache()
assert envs._is_envs_cache_enabled()
# Only wrap one-layer of cache, so we only need to
# call disable once to reset.
enable_envs_cache()
enable_envs_cache()
enable_envs_cache()
disable_envs_cache()
assert not envs._is_envs_cache_enabled()
disable_envs_cache()
assert not envs._is_envs_cache_enabled()
class TestEnvWithChoices: class TestEnvWithChoices:
"""Test cases for env_with_choices function.""" """Test cases for env_with_choices function."""

View File

@ -1586,6 +1586,8 @@ def destroy_distributed_environment():
def cleanup_dist_env_and_memory(shutdown_ray: bool = False): def cleanup_dist_env_and_memory(shutdown_ray: bool = False):
# Reset environment variable cache
envs.disable_envs_cache()
# Ensure all objects are not frozen before cleanup # Ensure all objects are not frozen before cleanup
gc.unfreeze() gc.unfreeze()

View File

@ -1580,6 +1580,12 @@ def __getattr__(name: str):
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
def _is_envs_cache_enabled() -> bool:
"""Checked if __getattr__ is wrapped with functools.cache"""
global __getattr__
return hasattr(__getattr__, "cache_clear")
def enable_envs_cache() -> None: def enable_envs_cache() -> None:
""" """
Enables caching of environment variables. This is useful for performance Enables caching of environment variables. This is useful for performance
@ -1590,6 +1596,9 @@ def enable_envs_cache() -> None:
runtime overhead. This also means that environment variables should NOT runtime overhead. This also means that environment variables should NOT
be updated after the service is initialized. be updated after the service is initialized.
""" """
if _is_envs_cache_enabled():
# Avoid wrapping functools.cache multiple times
return
# Tag __getattr__ with functools.cache # Tag __getattr__ with functools.cache
global __getattr__ global __getattr__
__getattr__ = functools.cache(__getattr__) __getattr__ = functools.cache(__getattr__)
@ -1599,6 +1608,17 @@ def enable_envs_cache() -> None:
__getattr__(key) __getattr__(key)
def disable_envs_cache() -> None:
"""
Resets the environment variables cache. It could be used to isolate environments
between unit tests.
"""
global __getattr__
# If __getattr__ is wrapped by functions.cache, unwrap the caching layer.
if _is_envs_cache_enabled():
__getattr__ = __getattr__.__wrapped__
def __dir__(): def __dir__():
return list(environment_variables.keys()) return list(environment_variables.keys())

View File

@ -211,6 +211,9 @@ class EngineCore:
freeze_gc_heap() freeze_gc_heap()
# If enable, attach GC debugger after static variable freeze. # If enable, attach GC debugger after static variable freeze.
maybe_attach_gc_debug_callback() maybe_attach_gc_debug_callback()
# Enable environment variable cache (e.g. assume no more
# environment variable overrides after this point)
enable_envs_cache()
def _initialize_kv_caches( def _initialize_kv_caches(
self, vllm_config: VllmConfig self, vllm_config: VllmConfig
@ -672,10 +675,6 @@ class EngineCoreProc(EngineCore):
assert addresses.coordinator_input is not None assert addresses.coordinator_input is not None
logger.info("Waiting for READY message from DP Coordinator...") logger.info("Waiting for READY message from DP Coordinator...")
# Enable environment variable cache (e.g. assume no more
# environment variable overrides after this point)
enable_envs_cache()
@contextmanager @contextmanager
def _perform_handshakes( def _perform_handshakes(
self, self,