Aggressively optimise fast path for allocation
This change introduces a per small sizeclass free list. That can be used to access the free objects for that sizeclass with minimal calculations being required. It changes to a partial bump ptr. We bump allocate a whole OS page worth of objects at a go, so we don't switch as frequently between bump and free list allocation. The code for the fast paths has been restructured to minimise the work required on the common case, and also it is all inlined for the common case. Allocating a zero sized object is moved off the fast path. Ask for 1 byte if you want to be fast.
This commit is contained in:
@@ -23,10 +23,8 @@ namespace snmalloc
|
||||
ModArray<NUM_SIZECLASSES, size_t> size;
|
||||
ModArray<NUM_SIZECLASSES, size_t> cache_friendly_mask;
|
||||
ModArray<NUM_SIZECLASSES, size_t> inverse_cache_friendly_mask;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> bump_ptr_start;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> short_bump_ptr_start;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> initial_link_ptr;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> short_initial_link_ptr;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> initial_offset_ptr;
|
||||
ModArray<NUM_SMALL_CLASSES, uint16_t> short_initial_offset_ptr;
|
||||
ModArray<NUM_MEDIUM_CLASSES, uint16_t> medium_slab_slots;
|
||||
|
||||
|
||||
@@ -35,10 +33,8 @@ namespace snmalloc
|
||||
size(),
|
||||
cache_friendly_mask(),
|
||||
inverse_cache_friendly_mask(),
|
||||
bump_ptr_start(),
|
||||
short_bump_ptr_start(),
|
||||
initial_link_ptr(),
|
||||
short_initial_link_ptr(),
|
||||
initial_offset_ptr(),
|
||||
short_initial_offset_ptr(),
|
||||
medium_slab_slots()
|
||||
{
|
||||
size_t curr = 1;
|
||||
@@ -71,19 +67,9 @@ namespace snmalloc
|
||||
size_t correction = SLAB_SIZE % size[i];
|
||||
|
||||
// First element in the block is the link
|
||||
initial_link_ptr[i] = static_cast<uint16_t>(correction);
|
||||
short_initial_link_ptr[i] =
|
||||
initial_offset_ptr[i] = static_cast<uint16_t>(correction);
|
||||
short_initial_offset_ptr[i] =
|
||||
static_cast<uint16_t>(header_size + short_correction);
|
||||
|
||||
// Move to object after link.
|
||||
auto short_after_link = short_initial_link_ptr[i] + size[i];
|
||||
size_t after_link = initial_link_ptr[i] + size[i];
|
||||
|
||||
// Bump ptr has bottom bit set.
|
||||
// In case we only have one object on this slab check for wrap around.
|
||||
short_bump_ptr_start[i] =
|
||||
static_cast<uint16_t>((short_after_link + 1) % SLAB_SIZE);
|
||||
bump_ptr_start[i] = static_cast<uint16_t>((after_link + 1) % SLAB_SIZE);
|
||||
}
|
||||
|
||||
for (sizeclass_t i = NUM_SMALL_CLASSES; i < NUM_SIZECLASSES; i++)
|
||||
@@ -97,21 +83,12 @@ namespace snmalloc
|
||||
static constexpr SizeClassTable sizeclass_metadata = SizeClassTable();
|
||||
|
||||
static inline constexpr uint16_t
|
||||
get_initial_bumpptr(sizeclass_t sc, bool is_short)
|
||||
get_initial_offset(sizeclass_t sc, bool is_short)
|
||||
{
|
||||
if (is_short)
|
||||
return sizeclass_metadata.short_bump_ptr_start[sc];
|
||||
return sizeclass_metadata.short_initial_offset_ptr[sc];
|
||||
|
||||
return sizeclass_metadata.bump_ptr_start[sc];
|
||||
}
|
||||
|
||||
static inline constexpr uint16_t
|
||||
get_initial_link(sizeclass_t sc, bool is_short)
|
||||
{
|
||||
if (is_short)
|
||||
return sizeclass_metadata.short_initial_link_ptr[sc];
|
||||
|
||||
return sizeclass_metadata.initial_link_ptr[sc];
|
||||
return sizeclass_metadata.initial_offset_ptr[sc];
|
||||
}
|
||||
|
||||
constexpr static inline size_t sizeclass_to_size(sizeclass_t sizeclass)
|
||||
|
||||
Reference in New Issue
Block a user