fix(tui): allocate graph history lazily #63
@@ -550,7 +550,7 @@ impl TuiTargetState {
|
|||||||
session: None,
|
session: None,
|
||||||
status: TargetStatus::Opening,
|
status: TargetStatus::Opening,
|
||||||
negotiated: None,
|
negotiated: None,
|
||||||
graph_history: VecDeque::with_capacity(HISTORY_LIMIT),
|
graph_history: VecDeque::new(),
|
||||||
last_sample: None,
|
last_sample: None,
|
||||||
|
|
|||||||
last_warning: None,
|
last_warning: None,
|
||||||
stats: StatsCollector::new(stats_config),
|
stats: StatsCollector::new(stats_config),
|
||||||
@@ -1019,6 +1019,11 @@ pub(super) struct LastSample {
|
|||||||
fn push_bounded<T>(items: &mut VecDeque<T>, item: T, limit: usize) {
|
fn push_bounded<T>(items: &mut VecDeque<T>, item: T, limit: usize) {
|
||||||
if items.len() == limit {
|
if items.len() == limit {
|
||||||
items.pop_front();
|
items.pop_front();
|
||||||
|
} else if items.len() == items.capacity() && items.capacity() >= limit / 2 {
|
||||||
|
// Growth is naturally exponential; once we're within reach of `limit`,
|
||||||
|
// reserve exactly up to it instead of letting the next doubling step
|
||||||
|
// overshoot it for long-running, heavily populated buffers.
|
||||||
|
items.reserve_exact(limit - items.len());
|
||||||
}
|
}
|
||||||
items.push_back(item);
|
items.push_back(item);
|
||||||
}
|
}
|
||||||
@@ -2225,6 +2230,11 @@ mod tests {
|
|||||||
target.stats.snapshot().packets.unique_replies,
|
target.stats.snapshot().packets.unique_replies,
|
||||||
HISTORY_LIMIT as u64 + 3
|
HISTORY_LIMIT as u64 + 3
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
target.graph_history.capacity() < HISTORY_LIMIT + HISTORY_LIMIT / 10,
|
||||||
|
"expected saturated history capacity to stay close to the limit, got {}",
|
||||||
|
target.graph_history.capacity()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in new issue
Block a user
For a target receiving at least 65,537 replies,
VecDeque's geometric growth increases this buffer's capacity from 65,536 to 131,072;push_boundedlater limits its length to 100,000 but never releases the 31,072 excess slots. Long-running active targets therefore retain more graph-history heap than the previous exact-limit allocation, with the overhead multiplied in multi-target runs, so grow the queue in capped increments or reserve only the final remainder as it approachesHISTORY_LIMIT.AGENTS.md reference: AGENTS.md:L53-L58
Useful? React with 👍 / 👎.
Fixed in
push_bounded: once capacity reaches half oflimit, we nowreserve_exactup tolimitinstead of letting the next geometric doubling overshoot it, so long-running targets no longer retain the extra ~31k slots.🤖 Addressed by Claude Code