Optimise buddy allocator to not search too high (#606)

The buddy allocator doesn't need to look at sizes above the current
highest size. This commit tracks the highest block that is stored in the
buddy allocator.
This commit is contained in:
Matthew Parkinson 2023-03-24 09:16:09 +00:00 коммит произвёл GitHub
Родитель 0620825df7
Коммит 8e3f6c96e8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 33 добавлений и 2 удалений

Просмотреть файл

@ -16,6 +16,8 @@ namespace snmalloc
class Buddy
{
std::array<RBTree<Rep>, MAX_SIZE_BITS - MIN_SIZE_BITS> trees;
// All RBtrees at or above this index should be empty.
size_t empty_at_or_above = 0;
size_t to_index(size_t size)
{
@ -37,6 +39,16 @@ namespace snmalloc
UNUSED(addr, size);
}
void invariant()
{
#ifndef NDEBUG
for (size_t i = empty_at_or_above; i < trees.size(); i++)
{
SNMALLOC_ASSERT(trees[i].is_empty());
}
#endif
}
public:
constexpr Buddy() = default;
/**
@ -52,6 +64,7 @@ namespace snmalloc
typename Rep::Contents add_block(typename Rep::Contents addr, size_t size)
{
auto idx = to_index(size);
empty_at_or_above = bits::max(empty_at_or_above, idx + 1);
validate_block(addr, size);
@ -74,8 +87,13 @@ namespace snmalloc
size *= 2;
addr = Rep::align_down(addr, size);
if (size == bits::one_at_bit(MAX_SIZE_BITS))
{
// Invariant should be checked on all non-tail return paths.
// Holds trivially here with current design.
invariant();
// Too big for this buddy allocator.
return addr;
}
return add_block(addr, size);
}
@ -87,6 +105,7 @@ namespace snmalloc
trees[idx].find(path, addr);
}
trees[idx].insert_path(path, addr);
invariant();
return Rep::null;
}
@ -97,7 +116,10 @@ namespace snmalloc
*/
typename Rep::Contents remove_block(size_t size)
{
invariant();
auto idx = to_index(size);
if (idx >= empty_at_or_above)
return Rep::null;
auto addr = trees[idx].remove_min();
if (addr != Rep::null)
@ -112,7 +134,11 @@ namespace snmalloc
auto bigger = remove_block(size * 2);
if (bigger == Rep::null)
{
empty_at_or_above = idx;
invariant();
return Rep::null;
}
auto second = Rep::offset(bigger, size);

Просмотреть файл

@ -730,9 +730,14 @@ namespace snmalloc
invariant();
}
bool is_empty()
{
return get_root().is_null();
}
K remove_min()
{
if (get_root().is_null())
if (is_empty())
return Rep::null;
auto path = get_root_path();
@ -748,7 +753,7 @@ namespace snmalloc
bool remove_elem(K value)
{
if (get_root().is_null())
if (is_empty())
return false;
auto path = get_root_path();