WIP: Functions: new local allocator for better memory reuse and performance #104630

Draft
Jacques Lucke wants to merge 44 commits from JacquesLucke/blender:local-allocator into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 17 additions and 23 deletions
Showing only changes of commit 6683b50bb1 - Show all commits

View File

@ -140,7 +140,7 @@ class ValueAllocator : NonCopyable, NonMovable {
* Use stacks so that the most recently used buffers are reused first. This improves cache
* efficiency.
*/
std::array<Vector<VariableValue *>, tot_variable_value_types> variable_value_free_lists_;
std::array<LocalAllocatorPool *, tot_variable_value_types> variable_value_free_lists_;
/**
* The integer key is the size of one element (e.g. 4 for an integer buffer). All buffers are
@ -159,17 +159,22 @@ class ValueAllocator : NonCopyable, NonMovable {
ValueAllocator(LocalAllocator &local_allocator, const int array_size)
: local_allocator_(local_allocator), array_size_(array_size)
{
this->prepare_variable_value_pool<VariableValue_GVArray>();
this->prepare_variable_value_pool<VariableValue_Span>();
this->prepare_variable_value_pool<VariableValue_GVVectorArray>();
this->prepare_variable_value_pool<VariableValue_GVectorArray>();
this->prepare_variable_value_pool<VariableValue_OneSingle>();
this->prepare_variable_value_pool<VariableValue_OneVector>();
}
template<typename T> void prepare_variable_value_pool()
{
variable_value_free_lists_[int(T::static_type)] = &local_allocator_.get_pool(sizeof(T),
alignof(T));
}
~ValueAllocator()
{
this->deallocate_variable_values<VariableValue_GVArray>();
this->deallocate_variable_values<VariableValue_Span>();
this->deallocate_variable_values<VariableValue_GVVectorArray>();
this->deallocate_variable_values<VariableValue_GVectorArray>();
this->deallocate_variable_values<VariableValue_OneSingle>();
this->deallocate_variable_values<VariableValue_OneVector>();
for (void *buffer : small_span_buffers_free_list_) {
local_allocator_.deallocate(
buffer, small_value_max_size * array_size_, small_value_max_alignment);
@ -192,13 +197,6 @@ class ValueAllocator : NonCopyable, NonMovable {
}
}
template<typename T> void deallocate_variable_values()
{
for (VariableValue *value : variable_value_free_lists_[int(T::static_type)]) {
local_allocator_.deallocate(value, sizeof(T), alignof(T));
}
}
VariableValue_GVArray *obtain_GVArray(const GVArray &varray)
{
return this->obtain<VariableValue_GVArray>(varray);
@ -331,20 +329,16 @@ class ValueAllocator : NonCopyable, NonMovable {
}
}
Vector<VariableValue *> &stack = variable_value_free_lists_[int(value->type)];
stack.append(value);
local_allocator_.deallocate(value, *variable_value_free_lists_[int(value->type)]);
}
private:
template<typename T, typename... Args> T *obtain(Args &&...args)
{
static_assert(std::is_base_of_v<VariableValue, T>);
Vector<VariableValue *> &stack = variable_value_free_lists_[int(T::static_type)];
if (stack.is_empty()) {
void *buffer = local_allocator_.allocate(sizeof(T), alignof(T));
return new (buffer) T(std::forward<Args>(args)...);
}
return new (stack.pop_last()) T(std::forward<Args>(args)...);
void *buffer = static_cast<T *>(
local_allocator_.allocate(*variable_value_free_lists_[int(T::static_type)]));
return new (buffer) T(std::forward<Args>(args)...);
}
};