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.
7 changed files with 17 additions and 15 deletions
Showing only changes of commit ae4672bd29 - Show all commits

View File

@ -284,7 +284,7 @@ class LazyFunction {
/**
* Destruct the storage created in #init_storage.
*/
virtual void destruct_storage(void *storage) const;
virtual void destruct_storage(void *storage, LocalPool<> &allocator) const;
/**
* Calls `fn` with the input indices that the given `output_index` may depend on. By default

View File

@ -93,7 +93,7 @@ inline void execute_lazy_function_eagerly_impl(
BasicParams params{
fn, input_pointers, output_pointers, input_usages, output_usages, set_outputs};
fn.execute(params, context);
fn.destruct_storage(context.storage);
fn.destruct_storage(context.storage, allocator);
/* Make sure all outputs have been computed. */
BLI_assert(!Span(set_outputs).contains(false));

View File

@ -89,7 +89,7 @@ class GraphExecutor : public LazyFunction {
const SideEffectProvider *side_effect_provider);
void *init_storage(LocalPool<> &allocator) const override;
void destruct_storage(void *storage) const override;
void destruct_storage(void *storage, LocalPool<> &allocator) const override;
private:
void execute_impl(Params &params, const Context &context) const override;

View File

@ -30,7 +30,7 @@ void *LazyFunction::init_storage(LocalPool<> & /*allocator*/) const
return nullptr;
}
void LazyFunction::destruct_storage(void *storage) const
void LazyFunction::destruct_storage(void *storage, LocalPool<> & /*allocator*/) const
{
BLI_assert(storage == nullptr);
UNUSED_VARS_NDEBUG(storage);

View File

@ -267,7 +267,7 @@ class Executor {
BLI_assert(self_.graph_.node_indices_are_valid());
}
~Executor()
void destruct_self(LocalPool<> & /*parent_allocator*/)
{
if (TaskPool *task_pool = task_pool_.load()) {
BLI_task_pool_free(task_pool);
@ -276,9 +276,10 @@ class Executor {
for (const int node_index : range) {
const Node &node = *self_.graph_.nodes()[node_index];
NodeState &node_state = *node_states_[node_index];
this->destruct_node_state(node, node_state);
this->destruct_node_state(node, node_state, this->get_main_or_local_allocator());
}
});
this->~Executor();
}
/**
@ -364,15 +365,14 @@ class Executor {
node_state.outputs = allocator.construct_array<OutputState>(node_outputs.size());
}
void destruct_node_state(const Node &node, NodeState &node_state)
void destruct_node_state(const Node &node, NodeState &node_state, LocalPool<> &allocator)
{
if (node.is_function()) {
const LazyFunction &fn = static_cast<const FunctionNode &>(node).function();
if (node_state.storage != nullptr) {
fn.destruct_storage(node_state.storage);
fn.destruct_storage(node_state.storage, allocator);
}
}
LocalPool<> &allocator = this->get_main_or_local_allocator();
for (const int i : node.inputs().index_range()) {
InputState &input_state = node_state.inputs[i];
const InputSocket &input_socket = node.input(i);
@ -891,7 +891,7 @@ class Executor {
if (node_state.storage != nullptr) {
if (node.is_function()) {
const FunctionNode &fn_node = static_cast<const FunctionNode &>(node);
fn_node.function().destruct_storage(node_state.storage);
fn_node.function().destruct_storage(node_state.storage, allocator);
}
node_state.storage = nullptr;
}
@ -1337,9 +1337,11 @@ void *GraphExecutor::init_storage(LocalPool<> &allocator) const
return &executor;
}
void GraphExecutor::destruct_storage(void *storage) const
void GraphExecutor::destruct_storage(void *storage, LocalPool<> &allocator) const
{
std::destroy_at(static_cast<Executor *>(storage));
Executor *executor = static_cast<Executor *>(storage);
executor->destruct_self(allocator);
allocator.deallocate(executor, sizeof(Executor), alignof(Executor));
}
void GraphExecutorLogger::log_socket_value(const Socket &socket,

View File

@ -1199,7 +1199,7 @@ static GeometrySet compute_geometry(
param_output_usages,
param_set_outputs};
graph_executor.execute(lf_params, lf_context);
graph_executor.destruct_storage(lf_context.storage);
graph_executor.destruct_storage(lf_context.storage, allocator);
for (GMutablePointer &ptr : inputs_to_destruct) {
ptr.destruct();

View File

@ -696,10 +696,10 @@ class LazyFunctionForGroupNode : public LazyFunction {
return s;
}
void destruct_storage(void *storage) const override
void destruct_storage(void *storage, LocalPool<> &allocator) const override
{
Storage *s = static_cast<Storage *>(storage);
graph_executor_->destruct_storage(s->graph_executor_storage);
graph_executor_->destruct_storage(s->graph_executor_storage, allocator);
std::destroy_at(s);
}
};