lean_ctx/core/
context_gc.rs1use crate::core::cache::SessionCache;
2
3const PRESSURE_THRESHOLD_TOKENS: usize = 50_000;
4const TARGET_AFTER_GC_TOKENS: usize = 35_000;
5
6#[allow(dead_code)]
7pub struct GcResult {
8 pub tokens_freed: usize,
9 pub tokens_before: usize,
10 pub tokens_after: usize,
11}
12
13pub(crate) fn should_run_gc(cache: &SessionCache) -> bool {
14 cache.total_cached_tokens() > PRESSURE_THRESHOLD_TOKENS
15}
16
17pub(crate) fn run_gc(cache: &mut SessionCache) -> GcResult {
18 let tokens_before = cache.total_cached_tokens();
19 if tokens_before <= PRESSURE_THRESHOLD_TOKENS {
20 return GcResult {
21 tokens_freed: 0,
22 tokens_before,
23 tokens_after: tokens_before,
24 };
25 }
26
27 cache.evict_to_budget(TARGET_AFTER_GC_TOKENS);
28 let tokens_after = cache.total_cached_tokens();
29
30 GcResult {
31 tokens_freed: tokens_before.saturating_sub(tokens_after),
32 tokens_before,
33 tokens_after,
34 }
35}
36
37pub fn maybe_gc(cache: &mut SessionCache) -> Option<GcResult> {
38 if should_run_gc(cache) {
39 Some(run_gc(cache))
40 } else {
41 None
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn gc_does_not_run_below_threshold() {
51 let cache = SessionCache::new();
52 assert!(!should_run_gc(&cache));
53 }
54}