Experimental optimization for the segment reclamation logic.

The goal is to improve efficiency of finding an abandoned segment that contains free space of the required size.
This change adds a free space bitmask to the segment object. More optimal place for the bitmask could be in the arena (i.e. extend the arena’s bitmask for abandoned segments to include size information too).
This commit is contained in:
Sergiy Kuryata 2024-10-31 16:53:14 -07:00
parent b604099334
commit 911de68d3e
5 changed files with 86 additions and 7 deletions

View file

@ -137,8 +137,10 @@ typedef struct mi_arena_field_cursor_s { // abstract
mi_arena_id_t start;
int count;
size_t bitmap_idx;
size_t free_space_mask;
} mi_arena_field_cursor_t;
void _mi_arena_field_cursor_init(mi_heap_t* heap, mi_arena_field_cursor_t* current);
void _mi_arena_field_cursor_init2(mi_heap_t* heap, mi_arena_field_cursor_t* current, size_t free_space_mask);
mi_segment_t* _mi_arena_segment_clear_abandoned_next(mi_arena_field_cursor_t* previous);
// "segment-map.c"
@ -945,6 +947,7 @@ static inline size_t mi_bsr(uintptr_t x) {
return (x==0 ? MI_INTPTR_BITS : MI_INTPTR_BITS - 1 - mi_clz(x));
}
size_t mi_free_space_mask_from_blocksize(size_t size);
// ---------------------------------------------------------------------------------
// Provide our own `_mi_memcpy` for potential performance optimizations.

View file

@ -220,6 +220,11 @@ typedef int32_t mi_ssize_t;
#define MI_MAX_ALLOC_SIZE PTRDIFF_MAX
#endif
#define MI_FREE_SPACE_MASK_BIT_COUNT 31
#define MI_FREE_SPACE_BINS_PER_BIT (MI_BIN_HUGE/MI_FREE_SPACE_MASK_BIT_COUNT)
#define MI_FREE_SPACE_MASK_ALL ((size_t)0xFFFFFFFF)
#define MI_FREE_SPACE_MASK_ABANDONED ((size_t)0x80000000)
#define MI_FREE_SPACE_MASK_ANY (MI_FREE_SPACE_MASK_ALL & (~MI_FREE_SPACE_MASK_ABANDONED))
// ------------------------------------------------------
// Mimalloc pages contain allocated blocks
@ -470,6 +475,7 @@ typedef struct mi_segment_s {
mi_segment_kind_t kind;
size_t slice_entries; // entries in the `slices` array, at most `MI_SLICES_PER_SEGMENT`
_Atomic(mi_threadid_t) thread_id; // unique id of the thread owning this segment
_Atomic(size_t) free_space_mask; // bitmask that indicates wich allocation sizes are available in this segment
mi_slice_t slices[MI_SLICES_PER_SEGMENT+1]; // one extra final entry for huge blocks with large alignment
} mi_segment_t;