use super::*;
#[test]
fn resident_ifds_batch_reuses_cached_csr_across_solves() {
let prepared = prepared_fixture();
let dispatch = FakeResidentDispatch::new();
let mut batch = ResidentIfdsBatch::new();
let seed_a = [(0, 0, 0)];
let seed_b = [(0, 1, 0)];
let first = batch
.solve_prepared_many(&dispatch, &prepared, &[&seed_a[..], &seed_b[..]], 4)
.expect("first resident IFDS batch solve must converge");
let second = batch
.solve_prepared(&dispatch, &prepared, &seed_b, 4)
.expect("second resident IFDS batch solve must reuse CSR");
assert_eq!(first, vec![vec![0], vec![1024]]);
assert_eq!(second, vec![1024]);
assert_eq!(
dispatch.allocate_calls.get(),
8,
"resident IFDS batch must allocate four unique CSR buffers and one reusable four-buffer parallel scratch set"
);
assert_eq!(
batch.stats(),
ResidentIfdsBatchStats {
csr_cache: ResidentIfdsCsrCacheStats {
hits: 1,
misses: 1,
resident_uploads: 1,
resident_upload_bytes: prepared.retained_graph_bytes() as u64,
resident_avoided_upload_bytes: prepared.retained_graph_bytes() as u64,
evictions: 0,
retained_bytes: prepared.retained_graph_bytes(),
entries: 1,
},
scratch_allocations: 1,
scratch_reuses: 1,
scratch_frees: 0,
resident_dispatches: 2,
seed_upload_bytes: 56,
result_readback_bytes: 12,
resident_graph_cold_uploads: 1,
resident_graph_warm_reuses: 1,
resident_graph_upload_bytes: prepared.retained_graph_bytes() as u64,
resident_graph_avoided_upload_bytes: prepared.retained_graph_bytes() as u64,
scratch_resident: true,
scratch_bytes: 48,
}
);
assert_eq!(
batch.csr_cache_stats(),
ResidentIfdsCsrCacheStats {
hits: 1,
misses: 1,
resident_uploads: 1,
resident_upload_bytes: prepared.retained_graph_bytes() as u64,
resident_avoided_upload_bytes: prepared.retained_graph_bytes() as u64,
evictions: 0,
retained_bytes: prepared.retained_graph_bytes(),
entries: 1,
}
);
assert_eq!(
batch.stats().resident_graph_reuse_telemetry(),
vyre::ResidentGraphReuseTelemetry::from_counters(
1,
1,
prepared.retained_graph_bytes() as u64,
prepared.retained_graph_bytes() as u64
),
"resident IFDS batch must expose CSR reuse through the shared Vyre graph-residency vocabulary"
);
assert_eq!(
dispatch.dispatches.get(),
8,
"resident IFDS fake dispatch should launch the bounded iteration window for each solve"
);
assert_eq!(
batch.csr_cache().len(),
1,
"resident IFDS batch must keep one invariant CSR layout resident"
);
batch
.free_all(&dispatch)
.expect("resident IFDS batch must free retained CSR resources");
assert_eq!(batch.csr_cache_stats().retained_bytes, 0);
assert_eq!(batch.stats().scratch_frees, 1);
assert!(!batch.stats().scratch_resident);
assert_eq!(batch.stats().scratch_bytes, 0);
assert_eq!(
dispatch.freed.borrow().len(),
8,
"resident IFDS batch free_all must release reusable scratch plus uniquely allocated cached CSR buffers"
);
}