fix(mem): 5s force floor so delegate-batch closes don't stack trims
Efficiency-pass follow-up on the #66355 salvage: force=True bypassed the cooldown entirely, and AIAgent.close() fires a forced trim for EVERY in-process child subagent close (delegate_tool child.close(), parent close step 5). A delegate batch of N children closing back-to-back in the gateway process stacked N+1 uncooled full gc.collect()+malloc_trim passes (50-500ms each with a large live heap). Forced trims now honor a 5s floor — bursts coalesce, the parent's final close-trim still fires. Guard test mutation-checked (floor zeroed -> test fails).
This commit is contained in:
@@ -200,6 +200,18 @@ def trim_memory(
|
||||
)
|
||||
if not force and _last_trim_monotonic and now - _last_trim_monotonic < cooldown:
|
||||
return False
|
||||
# Even forced trims honor a short floor: AIAgent.close() forces a trim,
|
||||
# and delegate batches close N child subagents back-to-back in the SAME
|
||||
# process — without a floor that stacks N+1 uncooled full gc.collect()
|
||||
# passes (50-500ms each in a large gateway process). 5s coalesces the
|
||||
# burst while keeping the parent's final close-trim effective.
|
||||
_FORCE_FLOOR_SECONDS = 5.0
|
||||
if (
|
||||
force
|
||||
and _last_trim_monotonic
|
||||
and now - _last_trim_monotonic < _FORCE_FLOOR_SECONDS
|
||||
):
|
||||
return False
|
||||
# Record the attempt before calling into libc so repeated failures do not
|
||||
# turn every turn boundary into an expensive full collection.
|
||||
_last_trim_monotonic = now
|
||||
|
||||
@@ -108,7 +108,10 @@ def test_force_logs_even_when_periodic_log_sampling_skips(monkeypatch, caplog):
|
||||
monkeypatch.setattr(mem_trim.gc, "collect", lambda: None)
|
||||
monkeypatch.setattr(mem_trim, "_malloc_trim", lambda _pad: 1)
|
||||
monkeypatch.setattr(mem_trim, "_config_settings", lambda: (True, 0.0, 99, 1.0))
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda: 100.0)
|
||||
# Two ticks: the forced call comes after the 5s force floor so it runs
|
||||
# (the floor exists to coalesce burst closes, not to mute logging).
|
||||
_ticks = iter([100.0, 110.0])
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda: next(_ticks, 110.0))
|
||||
monkeypatch.setattr(
|
||||
mem_trim,
|
||||
"collect_memory_snapshot",
|
||||
@@ -178,3 +181,36 @@ def test_libc_failure_is_fail_open_and_rate_limited(monkeypatch):
|
||||
assert mem_trim._last_trim_monotonic == 100.0
|
||||
assert mem_trim.trim_memory(cooldown_seconds=60) is False
|
||||
assert trim.call_count == 1
|
||||
|
||||
|
||||
def test_force_floor_coalesces_burst_closes(monkeypatch):
|
||||
"""A delegate batch closes N child agents back-to-back, each forcing a
|
||||
trim — the short force floor must coalesce the burst instead of stacking
|
||||
N uncooled full gc.collect() passes in the same process."""
|
||||
collect = Mock()
|
||||
trim = Mock(return_value=1)
|
||||
monkeypatch.setattr(mem_trim.gc, "collect", collect)
|
||||
monkeypatch.setattr(mem_trim, "_malloc_trim", trim)
|
||||
monkeypatch.setattr(mem_trim, "_config_settings", lambda: (True, 0.0, 1, 0.0))
|
||||
monkeypatch.setattr(
|
||||
mem_trim,
|
||||
"collect_memory_snapshot",
|
||||
lambda: {"rss_kib": 4096, "rss_anon_kib": 3072, "thread_count": 3},
|
||||
)
|
||||
monkeypatch.setattr(mem_trim, "_last_trim_monotonic", 0.0)
|
||||
|
||||
# t=100: first forced close runs.
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda: 100.0)
|
||||
assert mem_trim.trim_memory(force=True, reason="agent close") is True
|
||||
assert trim.call_count == 1
|
||||
|
||||
# t=101..103: three more child closes inside the floor — all coalesced.
|
||||
for t in (101.0, 102.0, 103.0):
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda t=t: t)
|
||||
assert mem_trim.trim_memory(force=True, reason="agent close") is False
|
||||
assert trim.call_count == 1, "burst closes must not stack forced trims"
|
||||
|
||||
# t=106: past the floor — the parent's final close-trim still fires.
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda: 106.0)
|
||||
assert mem_trim.trim_memory(force=True, reason="agent close") is True
|
||||
assert trim.call_count == 2
|
||||
|
||||
Reference in New Issue
Block a user