Skip to content

Streamline in-memory span eviction thresholds - #161

Merged
Yuge Zhang (ultmaster) merged 7 commits into
mainfrom
codex/add-span-eviction-for-inmemorylightningstore
Oct 16, 2025
Merged

Yuge Zhang (ultmaster) merged 7 commits into
mainfrom
codex/add-span-eviction-for-inmemorylightningstore

Conversation

@ultmaster

Copy link
Copy Markdown
Contributor

Summary

  • remove the explicit memory capacity override and rely on detected totals when resolving eviction thresholds
  • merge span size accounting into a single helper and evict rollouts strictly by start time once over threshold
  • patch memory detection in the unit suite and add a span-focused size estimation regression test

Testing

  • pytest tests/store/test_memory.py::test_span_eviction_removes_oldest_rollouts -q
  • pytest tests/store/test_memory.py::test_memory_threshold_accepts_byte_values -q
  • pytest tests/store/test_memory.py::test_memory_threshold_accepts_ratios_with_zero_safe -q
  • pytest tests/store/test_memory.py::test_invalid_safe_threshold_raises_value_error -q
  • pytest tests/store/test_memory.py::test_estimate_model_size_handles_span_objects -q

https://chatgpt.com/codex/tasks/task_e_68efc4dadcb0832eb776177b8647c3a0

Copilot AI review requested due to automatic review settings October 16, 2025 06:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

This PR streamlines memory management for span eviction in the in-memory store by replacing explicit capacity overrides with automatic memory detection and consolidating span size accounting. The key changes improve memory handling efficiency and add better test coverage for span-related functionality.

  • Remove explicit memory capacity overrides and rely on detected system memory totals
  • Merge span size accounting into unified helpers with strict start-time-based eviction
  • Add comprehensive test coverage for span eviction behavior and memory threshold validation

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
agentlightning/store/memory.py Implements new memory detection, threshold resolution, and span eviction logic with consolidated size accounting
tests/store/test_memory.py Adds test coverage for span eviction, memory threshold validation, and model size estimation functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread agentlightning/store/memory.py Outdated
Comment on lines +100 to +109
def _detect_total_memory_bytes() -> int:
"""Best-effort detection of the total available system memory in bytes."""

psutil_spec = importlib.util.find_spec("psutil")
if psutil_spec is not None:
psutil = importlib.import_module("psutil")
return int(psutil.virtual_memory().total)

# Fallback to 8GB if memory cannot be detected.
return 8 * 1024**3

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

Missing import statement for importlib.util in the imports section. The function uses importlib.util.find_spec but only importlib is imported.

Copilot uses AI. Check for mistakes.
Comment thread agentlightning/store/memory.py Outdated
Comment on lines +556 to +558
self._rollouts.get(rollout_id).start_time
if self._rollouts.get(rollout_id)
else spans[0].start_time or 0.0

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

Potential AttributeError if self._rollouts.get(rollout_id) returns None. The code attempts to access .start_time on a potentially None value. Consider using a single variable to store the rollout result.

Suggested change
self._rollouts.get(rollout_id).start_time
if self._rollouts.get(rollout_id)
else spans[0].start_time or 0.0
(self._rollouts.get(rollout_id).start_time if (rollout := self._rollouts.get(rollout_id)) is not None else spans[0].start_time or 0.0)

Copilot uses AI. Check for mistakes.
Comment thread tests/store/test_memory.py Outdated
+ sys.getsizeof(context.span_id)
+ sys.getsizeof(context.is_remote)
+ sys.getsizeof(context.trace_state)
+ sum(sys.getsizeof(v) for v in context.trace_state.values())

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

The test assumes context.trace_state has dictionary values, but line 664 shows it's initialized as an empty dict {}. The sum() over .values() will work but the size calculation logic may be incorrect for empty dictionaries.

Copilot uses AI. Check for mistakes.
Comment thread tests/store/test_memory.py Outdated
Comment on lines +705 to +710
if link.attributes is None:
link_attributes_expected = sys.getsizeof(None)
else:
link_attributes_expected = sys.getsizeof(link.attributes) + sum(
sys.getsizeof(v) for v in link.attributes.values()
)

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

Potential AttributeError when link.attributes is None (as set in line 666). The code attempts to call .values() on None, which will raise an AttributeError.

Suggested change
if link.attributes is None:
link_attributes_expected = sys.getsizeof(None)
else:
link_attributes_expected = sys.getsizeof(link.attributes) + sum(
sys.getsizeof(v) for v in link.attributes.values()
)
link_attributes_expected = sys.getsizeof(link.attributes) + sum(
sys.getsizeof(v) for v in (link.attributes.values() if link.attributes is not None else [])
)

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


Args:
eviction_memory_threshold: The threshold for evicting spans in bytes.
By default, it's 70% of the total VRAM available.

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

Corrected 'VRAM' to 'RAM' as this refers to system memory, not video memory.

Suggested change
By default, it's 70% of the total VRAM available.
By default, it's 70% of the total RAM available.

Copilot uses AI. Check for mistakes.
)
assert estimate_model_size(inner) == inner_expected

mapping_expected = sys.getsizeof(outer.mapping) + sum(sys.getsizeof(v) for v in outer.mapping.values())

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

The size calculation is incomplete. It should include the size of dictionary keys as well as values.

Suggested change
mapping_expected = sys.getsizeof(outer.mapping) + sum(sys.getsizeof(v) for v in outer.mapping.values())
mapping_expected = (
sys.getsizeof(outer.mapping)
+ sum(sys.getsizeof(k) for k in outer.mapping.keys())
+ sum(sys.getsizeof(v) for v in outer.mapping.values())
)

Copilot uses AI. Check for mistakes.
return sum(estimate_model_size(value) for value in values) + sys.getsizeof(cast(object, obj))
if isinstance(obj, MappingABC):
mapping = cast(Mapping[Any, Any], obj)
return sum(estimate_model_size(value) for value in mapping.values()) + sys.getsizeof(cast(object, obj))

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

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

The mapping size estimation is incomplete. It should include the size of dictionary keys as well as values.

Suggested change
return sum(estimate_model_size(value) for value in mapping.values()) + sys.getsizeof(cast(object, obj))
return sum(estimate_model_size(key) + estimate_model_size(value) for key, value in mapping.items()) + sys.getsizeof(cast(object, obj))

Copilot uses AI. Check for mistakes.
…x/add-span-eviction-for-inmemorylightningstore
@ultmaster
Yuge Zhang (ultmaster) merged commit 8c673c2 into main Oct 16, 2025
12 checks passed
@ultmaster
Yuge Zhang (ultmaster) deleted the codex/add-span-eviction-for-inmemorylightningstore branch October 28, 2025 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants