From 5fd3288997dff464b06fdb17890380a9b6aa8a55 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Thu, 25 Nov 2021 13:43:50 +0000 Subject: [PATCH] Modify heuristic for adding new slabs. (#429) If there is only one slab remaining, then we probabalisticly allocator a new one. If a slab is barely in use, then this could cause us to effectively double the number of slabs in use. This commit checks if the remaining slab has enough remaining elements to provide randomisation. --- src/ds/seqset.h | 8 ++++++++ src/mem/corealloc.h | 13 +++++++++---- src/mem/freelist.h | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/ds/seqset.h b/src/ds/seqset.h index 13f9faf..da5eb46 100644 --- a/src/ds/seqset.h +++ b/src/ds/seqset.h @@ -159,5 +159,13 @@ namespace snmalloc v.end = &(item->next); } } + + /** + * Peek at next element in the set. + */ + SNMALLOC_FAST_PATH const T* peek() + { + return v.head; + } }; } // namespace snmalloc diff --git a/src/mem/corealloc.h b/src/mem/corealloc.h index 89adfc8..f5f03f8 100644 --- a/src/mem/corealloc.h +++ b/src/mem/corealloc.h @@ -689,11 +689,16 @@ namespace snmalloc { #ifdef SNMALLOC_CHECK_CLIENT // Occassionally don't use the last list. - if ( - SNMALLOC_UNLIKELY(alloc_classes[sizeclass].length == 1) && - (entropy.next_bit() == 0)) + if (SNMALLOC_UNLIKELY(alloc_classes[sizeclass].length == 1)) { - return small_alloc_slow(sizeclass, fast_free_list); + // If the slab has a lot of free space, then we shouldn't allocate a + // new slab. + auto min = alloc_classes[sizeclass] + .available.peek() + ->free_queue.min_list_length(); + if ((min * 2) < threshold_for_waking_slab(sizeclass)) + if (entropy.next_bit() == 0) + return small_alloc_slow(sizeclass, fast_free_list); } #endif diff --git a/src/mem/freelist.h b/src/mem/freelist.h index d2e5a18..fbd8509 100644 --- a/src/mem/freelist.h +++ b/src/mem/freelist.h @@ -740,6 +740,20 @@ namespace snmalloc UNUSED(domesticate); #endif } + + /** + * Returns length of the shorter free list. + * + * This method is only usable if the free list is adding randomisation + * as that is when it has two lists. + */ + template + [[nodiscard]] std::enable_if_t min_list_length() const + { + static_assert(RANDOM_ == RANDOM, "Don't set SFINAE parameter!"); + + return length[0] < length[1] ? length[0] : length[1]; + } }; } // namespace freelist } // namespace snmalloc