config: the lazy imports that buy nothing become eager (#36975)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Cheng Wan
2026-08-29 04:21:54 -07:00
committed by GitHub
co-authored by Claude Opus 5
parent f0d621cfa6
commit 4d53767b09
38 changed files with 173 additions and 271 deletions
@@ -30,9 +30,10 @@ under its own default configuration.
"""
import unittest
from unittest import mock
from types import SimpleNamespace
from sglang.srt.arg_groups.kv_cache_hook import handle_page_major_kv_layout
from sglang.srt.configs.model_config import AttentionArch
from sglang.srt.server_args import ServerArgs
from sglang.test.ci.ci_register import register_cpu_ci
@@ -67,18 +68,18 @@ def _accepts(
"mamba_backend": "triton",
}.items():
object.__setattr__(sa, name, value)
# `use_mla_backend` asks the model configuration, which this stand-in has
# no room for; the case under test is what the handler does with the answer.
# The handler imports it inside the function, so the source module is
# where the patch has to go.
with mock.patch(
"sglang.srt.arg_groups.overrides.use_mla_backend", return_value=use_mla
):
try:
handle_page_major_kv_layout(sa)
return True
except AssertionError:
return False
object.__setattr__(
sa,
"_model_config",
SimpleNamespace(
attention_arch=AttentionArch.MLA if use_mla else AttentionArch.MHA
),
)
try:
handle_page_major_kv_layout(sa)
return True
except AssertionError:
return False
class TestPageMajorBackendAllowlist(unittest.TestCase):
@@ -934,47 +934,42 @@ class TestDeclaredValuesAreNotEditedLater(CustomTestCase):
self.addCleanup(restore)
def _resolve_recording_each_entry(self, **supplied):
"""Resolve, deep-copying every stash entry the moment it is appended."""
from sglang.srt.arg_groups import overrides
"""Resolve, deep-copying every stash entry the moment it is appended.
The property is about the stash, so the seam is the stash: a list that
snapshots on append. Every declaration path -- `declare_resolution`,
`declare_late_resolution`, `declare_direct_writes` and the passes --
reaches it through `.append`, whatever it was imported as.
"""
recorded = []
def watch(name):
original = getattr(overrides, name)
class _SnapshotOnAppend(list):
def append(self, entry):
super().append(entry)
recorded.append((len(self) - 1, copy.deepcopy(entry)))
def wrapper(server_args, *args, **kwargs):
result = original(server_args, *args, **kwargs)
stash = getattr(server_args, "_resolved_overrides", None) or []
while len(recorded) < len(stash):
index = len(recorded)
recorded.append((index, copy.deepcopy(stash[index])))
return result
class _WatchedArgs(ServerArgs):
"""Whatever list the pipeline installs, snapshot what lands in it.
return original, wrapper
The pipeline resets the stash at the start of a resolution, so the
seam has to survive that assignment rather than precede it.
"""
# Every path that appends to the stash.
patched = {}
for name in (
"declare_resolution",
"declare_late_resolution",
"declare_direct_writes",
"run_post_process_pass",
):
original, wrapper = watch(name)
patched[name] = original
setattr(overrides, name, wrapper)
try:
path = tempfile.mkdtemp(prefix="declared_values_")
self.addCleanup(shutil.rmtree, path, ignore_errors=True)
with open(os.path.join(path, "config.json"), "w") as handle:
json.dump(_MINI_CONFIG, handle)
server_args = ServerArgs(
model_path=path, device="cuda", random_seed=42, **supplied
)
server_args.resolve_once()
finally:
for name, original in patched.items():
setattr(overrides, name, original)
def __setattr__(self, name, value):
if name == "_resolved_overrides" and not isinstance(
value, _SnapshotOnAppend
):
value = _SnapshotOnAppend(value)
super().__setattr__(name, value)
path = tempfile.mkdtemp(prefix="declared_values_")
self.addCleanup(shutil.rmtree, path, ignore_errors=True)
with open(os.path.join(path, "config.json"), "w") as handle:
json.dump(_MINI_CONFIG, handle)
server_args = _WatchedArgs(
model_path=path, device="cuda", random_seed=42, **supplied
)
server_args.resolve_once()
return server_args, recorded
def test_no_entry_changes_after_it_is_recorded(self):
@@ -979,10 +979,7 @@ class TestFa4PageSizeAutoForce(CustomTestCase):
return args
@patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True)
@patch("sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False)
def test_combined_attention_backend_fa4_forces_page_size_128(
self, _mock_mla, _mock_sm100
):
def test_combined_attention_backend_fa4_forces_page_size_128(self, _mock_sm100):
# `--attention-backend fa4` (combined): prefill/decode fields stay None.
args = self._make_args(attention_backend="fa4")
@@ -994,8 +991,7 @@ class TestFa4PageSizeAutoForce(CustomTestCase):
self.assertEqual(resolved_view(args).page_size, 128)
@patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True)
@patch("sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False)
def test_explicit_prefill_fa4_forces_page_size_128(self, _mock_mla, _mock_sm100):
def test_explicit_prefill_fa4_forces_page_size_128(self, _mock_sm100):
# `--prefill-attention-backend fa4`: the previously-covered path.
args = self._make_args(attention_backend=None, prefill="fa4", page_size=1)
@@ -1869,12 +1865,7 @@ class TestCudaGraphDisaggregationRoles(CustomTestCase):
is_multimodal=False,
is_multimodal_piecewise_cuda_graph_supported=False,
)
with (
patch("sglang.srt.utils.is_cuda", return_value=True),
patch(
"sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False
),
):
with patch("sglang.srt.utils.is_cuda", return_value=True):
handle_cuda_graph_config(args)
return args
@@ -1944,12 +1935,7 @@ class TestPrefillCudaGraphLoRACompatibility(CustomTestCase):
is_multimodal=False,
is_multimodal_piecewise_cuda_graph_supported=False,
)
with (
patch("sglang.srt.utils.is_cuda", return_value=True),
patch(
"sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False
),
):
with patch("sglang.srt.utils.is_cuda", return_value=True):
handle_cuda_graph_config(args)
return args
@@ -2010,12 +1996,7 @@ class TestBreakableCudaGraphMultimodalAllowlist(CustomTestCase):
is_multimodal_piecewise_cuda_graph_supported=False,
is_multimodal_breakable_cuda_graph_supported=allowlisted,
)
with (
patch("sglang.srt.utils.is_cuda", return_value=True),
patch(
"sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False
),
):
with patch("sglang.srt.utils.is_cuda", return_value=True):
handle_cuda_graph_config(args)
return args