Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ def _translate_full_to_swa(self, full_indices: torch.Tensor) -> torch.Tensor:
full_indices
)

def refresh_lru_on_walkdown(self, node: UnifiedTreeNode) -> None:
return

def _bounded_refresh(
self, last_node: UnifiedTreeNode, root_node: UnifiedTreeNode
) -> None:
self.cache.lru_lists[self.component_type].reset_node_and_window_ancestors_mru(
last_node,
root_node,
self.sliding_window_size + self.cache.page_size,
self.node_has_component_data,
)

def refresh_lru_on_match_end(
self, last_node: UnifiedTreeNode, root_node: UnifiedTreeNode
) -> None:
self._bounded_refresh(last_node, root_node)

def refresh_lru_on_insert_end(
self, target_node: UnifiedTreeNode, root_node: UnifiedTreeNode
) -> None:
self._bounded_refresh(target_node, root_node)

def _restore_device_value(self, node: UnifiedTreeNode, value: torch.Tensor) -> None:
ct = self.component_type
node.component_data[ct].value = value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,24 @@ def value_len(self, node: UnifiedTreeNode) -> int:
value = node.component_data[self.component_type].value
return len(value) if value is not None else 0

def refresh_lru_on_walkdown(self, node: UnifiedTreeNode) -> None:

@hzh0425 hzh0425 May 30, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we avoid adding too many new component interfaces here?
Could we instead merge them into a single interface and use a "phase" parameter to distinguish between different cases?

Additionally, it seems that refresh_lru_on_walkdown hasn't been implemented yet on swa_component

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to less inferfaces and use phrases.

add comment to indicate why we don't need to do anything in walkdown for swa to avoid confusing.

cd = node.component_data[self.component_type]
if cd.value is None:
return
self.cache.lru_lists[self.component_type].reset_node_mru(node)

def refresh_lru_on_match_end(
self, last_node: UnifiedTreeNode, root_node: UnifiedTreeNode
) -> None:
self.cache.lru_lists[self.component_type].reset_node_and_parents_mru(
last_node, root_node, self.node_has_component_data
)

def refresh_lru_on_insert_end(
self, target_node: UnifiedTreeNode, root_node: UnifiedTreeNode
) -> None:
return

@abstractmethod
def create_match_validator(
self, match_device_only: bool = False
Expand Down
34 changes: 30 additions & 4 deletions python/sglang/srt/mem_cache/unified_radix_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,24 @@ def reset_node_and_parents_mru(
prev_node = node
node = node.parent

def reset_node_and_window_ancestors_mru(
self,
node: UnifiedTreeNode,
root_node: UnifiedTreeNode,
window_size: int,
should_include,
):
prev_node = self.head
accumulated = 0
while node != root_node and accumulated < window_size:
if should_include(node):
assert node.id in self.cache
self._remove_node(node)
self._add_node_after(prev_node, node)
prev_node = node
accumulated += len(node.key)
node = node.parent

def in_list(self, node: Optional[UnifiedTreeNode]):
return node is not None and node.id in self.cache

Expand Down Expand Up @@ -779,9 +797,7 @@ def _match_post_processor(
for comp in self._components_tuple:
if comp.component_type == BASE_COMPONENT_TYPE:
continue # Full uses last_access_time, not LRU
self.lru_lists[comp.component_type].reset_node_and_parents_mru(
node_update, self.root_node, comp.node_has_component_data
)
comp.refresh_lru_on_match_end(node_update, self.root_node)

cur_time = get_and_increase_time_counter()
while node_update:
Expand Down Expand Up @@ -855,7 +871,10 @@ def _split_node(
def _touch_node(self, node: UnifiedTreeNode):
node.last_access_time = get_and_increase_time_counter()
if node != self.root_node:
self._for_each_component_lru(node, UnifiedLRUList.reset_node_mru)
for comp in self._components_tuple:
if comp.component_type == BASE_COMPONENT_TYPE:
continue
comp.refresh_lru_on_walkdown(node)

def _add_new_node(
self,
Expand Down Expand Up @@ -985,6 +1004,13 @@ def _insert_helper(
params=params,
result=result,
)

if target_node is not self.root_node:
for component in self._components_tuple:
if component.component_type == BASE_COMPONENT_TYPE:
continue
component.refresh_lru_on_insert_end(target_node, self.root_node)

if is_new_leaf:
self._inc_hit_count(target_node, params.chunked)
return result
Expand Down
Loading
Loading