-
Notifications
You must be signed in to change notification settings - Fork 14
recycle empty arenas in arena2 and mempool3 allocator #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -89,6 +89,71 @@ fn arc_drop() { | |
| assert_eq!(allocator.arenas_len(), 0); | ||
| } | ||
|
|
||
| #[test] | ||
| fn recycled_arena_avoids_realloc() { | ||
| let mut allocator = ArenaAllocator::default().with_arena_size(512); | ||
|
|
||
| let mut ptrs = Vec::new(); | ||
| for i in 0..16 { | ||
| ptrs.push(allocator.try_alloc(i).unwrap().as_ptr()); | ||
| } | ||
| assert_eq!(allocator.arenas_len(), 1); | ||
| // heap_size counts only live arenas, so capture it while one is active. | ||
| let heap_while_live = allocator.heap_size(); | ||
| assert_eq!(heap_while_live, 512); | ||
|
|
||
| for mut ptr in ptrs { | ||
| unsafe { ptr.as_mut().mark_dropped() }; | ||
| } | ||
| allocator.drop_dead_arenas(); | ||
|
|
||
| // After recycling, the arena is parked, no live arenas, so heap_size is 0. | ||
| assert_eq!(allocator.arenas_len(), 0); | ||
| assert_eq!(allocator.heap_size(), 0); | ||
| // recycled_count == 1 proves the arena was parked in the recycle slot, not freed to the OS. | ||
| assert_eq!(allocator.recycled_count, 1); | ||
|
|
||
| // Allocate again, must reuse the recycled arena without growing OS footprint. | ||
| // heap_size returns to the same value as when a live arena was present. | ||
| for i in 16..32 { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this show us that the arena is recycled? How do we know it's recycled the same memory?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I have added two recycled_count assertions to the test to verify that, Together these two checks confirm that the recycling process worked correctly. |
||
| let _ = allocator.try_alloc(i).unwrap(); | ||
| } | ||
| assert_eq!(allocator.arenas_len(), 1); | ||
| assert_eq!(allocator.heap_size(), heap_while_live); | ||
| // recycled_count == 0 proves the recycled slot was consumed rather than a new OS allocation. | ||
| assert_eq!(allocator.recycled_count, 0); | ||
| } | ||
|
|
||
| #[test] | ||
| fn max_recycled_cap_respected() { | ||
| let mut allocator = ArenaAllocator::default().with_arena_size(128); | ||
|
|
||
| let mut ptrs_per_arena: Vec<Vec<NonNull<ArenaHeapItem<u64>>>> = Vec::new(); | ||
|
|
||
| for _ in 0..5 { | ||
| let mut ptrs = Vec::new(); | ||
| let target_len = allocator.arenas_len() + 1; | ||
| while allocator.arenas_len() < target_len { | ||
| ptrs.push(allocator.try_alloc(0u64).unwrap().as_ptr()); | ||
| } | ||
| ptrs_per_arena.push(ptrs); | ||
| } | ||
| assert_eq!(allocator.arenas_len(), 5); | ||
|
|
||
| for ptrs in ptrs_per_arena { | ||
| for mut ptr in ptrs { | ||
| unsafe { ptr.as_mut().mark_dropped() }; | ||
| } | ||
| } | ||
|
|
||
| allocator.drop_dead_arenas(); | ||
|
|
||
| assert_eq!(allocator.arenas_len(), 0); | ||
| assert_eq!(allocator.heap_size(), 0); | ||
| // The recycled list holds exactly max_recycled pages. | ||
| assert_eq!(allocator.recycled_count, 4); | ||
| } | ||
|
|
||
| // === test for TaggedPtr::as_ptr === // | ||
|
|
||
| // `TaggedPtr::as_ptr` must use `addr & !MASK` to unconditionally clear the high | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought: we should probably zero out the memory here to as a proper reset to be "good citizens" so to speak.
I'm not convinced that blocks this PR though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
write_bytes(0)over the full layout size to zero the buffer. This prevents stale object graphs from being observable through any future partial walk of a recycled arena