Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-11-21 14:37:04 +0300
committerJacques Lucke <jacques@blender.org>2021-11-21 14:48:07 +0300
commit6ee2abde82ef121cd6e927995053ac33afdbb438 (patch)
treef2ed1bb0962c0ea60c30ba7d9dea2a6e184ec247 /source/blender/functions
parentd455eadcd82f2151e858025cae6788b65016811e (diff)
Functions: use static names for multi-functions
Previously, the function names were stored in `std::string` and were often created dynamically (especially when the function just output a constant). This resulted in a lot of overhead. Now the function name is just a `const char *` that should be statically allocated. This is good enough for the majority of cases. If a multi-function needs a more dynamic name, it can override the `MultiFunction::debug_name` method. In my test file with >400,000 simple math nodes, the execution time improves from 3s to 1s.
Diffstat (limited to 'source/blender/functions')
-rw-r--r--source/blender/functions/FN_multi_function.hh2
-rw-r--r--source/blender/functions/FN_multi_function_builder.hh34
-rw-r--r--source/blender/functions/FN_multi_function_procedure_executor.hh2
-rw-r--r--source/blender/functions/FN_multi_function_signature.hh13
-rw-r--r--source/blender/functions/intern/field.cc7
-rw-r--r--source/blender/functions/intern/multi_function.cc5
-rw-r--r--source/blender/functions/intern/multi_function_builder.cc36
-rw-r--r--source/blender/functions/intern/multi_function_procedure.cc2
-rw-r--r--source/blender/functions/intern/multi_function_procedure_executor.cc5
-rw-r--r--source/blender/functions/tests/FN_multi_function_procedure_test.cc14
10 files changed, 54 insertions, 66 deletions
diff --git a/source/blender/functions/FN_multi_function.hh b/source/blender/functions/FN_multi_function.hh
index c57f6cf574e..3059fe59ca7 100644
--- a/source/blender/functions/FN_multi_function.hh
+++ b/source/blender/functions/FN_multi_function.hh
@@ -97,6 +97,8 @@ class MultiFunction {
return signature_ref_->function_name;
}
+ virtual std::string debug_name() const;
+
bool depends_on_context() const
{
return signature_ref_->depends_on_context;
diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index 0ce05cbca30..eaf9e5ce70f 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -43,7 +43,7 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
MFSignature signature_;
public:
- CustomMF_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -53,7 +53,7 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
}
template<typename ElementFuncT>
- CustomMF_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SO(name, CustomMF_SI_SO::create_function(element_fn))
{
}
@@ -92,7 +92,7 @@ class CustomMF_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -103,7 +103,7 @@ class CustomMF_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SO(name, CustomMF_SI_SI_SO::create_function(element_fn))
{
}
@@ -150,7 +150,7 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -162,7 +162,7 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SO::create_function(element_fn))
{
}
@@ -211,7 +211,7 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -224,7 +224,7 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SI_SO::create_function(element_fn))
{
}
@@ -265,7 +265,7 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SM(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SM(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_mutable<Mut1>("Mut1");
@@ -274,7 +274,7 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SM(StringRef name, ElementFuncT element_fn)
+ CustomMF_SM(const char *name, ElementFuncT element_fn)
: CustomMF_SM(name, CustomMF_SM::create_function(element_fn))
{
}
@@ -306,8 +306,8 @@ template<typename From, typename To> class CustomMF_Convert : public MultiFuncti
static MFSignature create_signature()
{
- std::string name = CPPType::get<From>().name() + " to " + CPPType::get<To>().name();
- MFSignatureBuilder signature{std::move(name)};
+ static std::string name = CPPType::get<From>().name() + " to " + CPPType::get<To>().name();
+ MFSignatureBuilder signature{name.c_str()};
signature.single_input<From>("Input");
signature.single_output<To>("Output");
return signature.build();
@@ -372,9 +372,7 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
template<typename U> CustomMF_Constant(U &&value) : value_(std::forward<U>(value))
{
MFSignatureBuilder signature{"Constant"};
- std::stringstream ss;
- ss << value_;
- signature.single_output<T>(ss.str());
+ signature.single_output<T>("Value");
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -414,9 +412,7 @@ class CustomMF_DefaultOutput : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_DefaultOutput(StringRef name,
- Span<MFDataType> input_types,
- Span<MFDataType> output_types);
+ CustomMF_DefaultOutput(Span<MFDataType> input_types, Span<MFDataType> output_types);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
@@ -425,7 +421,7 @@ class CustomMF_GenericCopy : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_GenericCopy(StringRef name, MFDataType data_type);
+ CustomMF_GenericCopy(MFDataType data_type);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
diff --git a/source/blender/functions/FN_multi_function_procedure_executor.hh b/source/blender/functions/FN_multi_function_procedure_executor.hh
index 9c8b59739b8..b12e3a91210 100644
--- a/source/blender/functions/FN_multi_function_procedure_executor.hh
+++ b/source/blender/functions/FN_multi_function_procedure_executor.hh
@@ -31,7 +31,7 @@ class MFProcedureExecutor : public MultiFunction {
const MFProcedure &procedure_;
public:
- MFProcedureExecutor(std::string name, const MFProcedure &procedure);
+ MFProcedureExecutor(const MFProcedure &procedure);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
diff --git a/source/blender/functions/FN_multi_function_signature.hh b/source/blender/functions/FN_multi_function_signature.hh
index d05948cc645..2ccaa60fed6 100644
--- a/source/blender/functions/FN_multi_function_signature.hh
+++ b/source/blender/functions/FN_multi_function_signature.hh
@@ -30,7 +30,14 @@
namespace blender::fn {
struct MFSignature {
- std::string function_name;
+ /**
+ * The name should be statically allocated so that it lives longer than this signature. This is
+ * used instead of an #std::string because of the overhead when many functions are created.
+ * If the name of the function has to be more dynamic for debugging purposes, override
+ * #MultiFunction::debug_name() instead. Then the dynamic name will only be computed when it is
+ * actually needed.
+ */
+ const char *function_name;
Vector<std::string> param_names;
Vector<MFParamType> param_types;
Vector<int> param_data_indices;
@@ -51,9 +58,9 @@ class MFSignatureBuilder {
int vector_array_count_ = 0;
public:
- MFSignatureBuilder(std::string function_name)
+ MFSignatureBuilder(const char *function_name)
{
- signature_.function_name = std::move(function_name);
+ signature_.function_name = function_name;
}
MFSignature build() const
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 68a8446e6ae..91b1bdfd8f0 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -237,8 +237,7 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
if (!already_output_variables.add(variable)) {
/* One variable can be output at most once. To output the same value twice, we have to make
* a copy first. */
- const MultiFunction &copy_fn = scope.construct<CustomMF_GenericCopy>("copy",
- variable->data_type());
+ const MultiFunction &copy_fn = scope.construct<CustomMF_GenericCopy>(variable->data_type());
variable = builder.add_call<1>(copy_fn, {variable})[0];
}
builder.add_output_parameter(*variable);
@@ -358,7 +357,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
MFProcedure procedure;
build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, varying_fields_to_evaluate);
- MFProcedureExecutor procedure_executor{"Procedure", procedure};
+ MFProcedureExecutor procedure_executor{procedure};
/* Add multi threading capabilities to the field evaluation. */
const int grain_size = 10000;
fn::ParallelMultiFunction parallel_procedure_executor{procedure_executor, grain_size};
@@ -415,7 +414,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
MFProcedure procedure;
build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, constant_fields_to_evaluate);
- MFProcedureExecutor procedure_executor{"Procedure", procedure};
+ MFProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context;
diff --git a/source/blender/functions/intern/multi_function.cc b/source/blender/functions/intern/multi_function.cc
index 43eacdcd2a1..ee2c69068db 100644
--- a/source/blender/functions/intern/multi_function.cc
+++ b/source/blender/functions/intern/multi_function.cc
@@ -18,4 +18,9 @@
namespace blender::fn {
+std::string MultiFunction::debug_name() const
+{
+ return signature_ref_->function_name;
+}
+
} // namespace blender::fn
diff --git a/source/blender/functions/intern/multi_function_builder.cc b/source/blender/functions/intern/multi_function_builder.cc
index f891f162820..24f9bbe0179 100644
--- a/source/blender/functions/intern/multi_function_builder.cc
+++ b/source/blender/functions/intern/multi_function_builder.cc
@@ -32,10 +32,8 @@ CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
}
value_ = value;
- MFSignatureBuilder signature{"Constant " + type.name()};
- std::stringstream ss;
- type.print_or_default(value, ss, type.name());
- signature.single_output(ss.str(), type);
+ MFSignatureBuilder signature{"Constant"};
+ signature.single_output("Value", type);
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -73,28 +71,11 @@ bool CustomMF_GenericConstant::equals(const MultiFunction &other) const
return type_.is_equal(value_, _other->value_);
}
-static std::string gspan_to_string(GSpan array)
-{
- const CPPType &type = array.type();
- std::stringstream ss;
- ss << "[";
- const int64_t max_amount = 5;
- for (int64_t i : IndexRange(std::min(max_amount, array.size()))) {
- type.print_or_default(array[i], ss, type.name());
- ss << ", ";
- }
- if (max_amount < array.size()) {
- ss << "...";
- }
- ss << "]";
- return ss.str();
-}
-
CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array)
{
const CPPType &type = array.type();
- MFSignatureBuilder signature{"Constant " + type.name() + " Vector"};
- signature.vector_output(gspan_to_string(array), type);
+ MFSignatureBuilder signature{"Constant Vector"};
+ signature.vector_output("Value", type);
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -109,12 +90,11 @@ void CustomMF_GenericConstantArray::call(IndexMask mask,
}
}
-CustomMF_DefaultOutput::CustomMF_DefaultOutput(StringRef name,
- Span<MFDataType> input_types,
+CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<MFDataType> input_types,
Span<MFDataType> output_types)
: output_amount_(output_types.size())
{
- MFSignatureBuilder signature{name};
+ MFSignatureBuilder signature{"Default Output"};
for (MFDataType data_type : input_types) {
signature.input("Input", data_type);
}
@@ -140,9 +120,9 @@ void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext UNU
}
}
-CustomMF_GenericCopy::CustomMF_GenericCopy(StringRef name, MFDataType data_type)
+CustomMF_GenericCopy::CustomMF_GenericCopy(MFDataType data_type)
{
- MFSignatureBuilder signature{name};
+ MFSignatureBuilder signature{"Copy"};
signature.input("Input", data_type);
signature.output("Output", data_type);
signature_ = signature.build();
diff --git a/source/blender/functions/intern/multi_function_procedure.cc b/source/blender/functions/intern/multi_function_procedure.cc
index 986c5dff0c4..804beb7d66f 100644
--- a/source/blender/functions/intern/multi_function_procedure.cc
+++ b/source/blender/functions/intern/multi_function_procedure.cc
@@ -782,7 +782,7 @@ class MFProcedureDotExport {
void instruction_to_string(const MFCallInstruction &instruction, std::stringstream &ss)
{
const MultiFunction &fn = instruction.fn();
- this->instruction_name_format(fn.name() + ": ", ss);
+ this->instruction_name_format(fn.debug_name() + ": ", ss);
for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index);
const MFVariable *variable = instruction.params()[param_index];
diff --git a/source/blender/functions/intern/multi_function_procedure_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc
index 85d0cf4909f..1136b03ed58 100644
--- a/source/blender/functions/intern/multi_function_procedure_executor.cc
+++ b/source/blender/functions/intern/multi_function_procedure_executor.cc
@@ -20,10 +20,9 @@
namespace blender::fn {
-MFProcedureExecutor::MFProcedureExecutor(std::string name, const MFProcedure &procedure)
- : procedure_(procedure)
+MFProcedureExecutor::MFProcedureExecutor(const MFProcedure &procedure) : procedure_(procedure)
{
- MFSignatureBuilder signature(std::move(name));
+ MFSignatureBuilder signature("Procedure Executor");
for (const ConstMFParameter &param : procedure.params()) {
signature.add(param.variable->name(), MFParamType(param.type, param.variable->data_type()));
diff --git a/source/blender/functions/tests/FN_multi_function_procedure_test.cc b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
index a0919d7926e..e3de23550c5 100644
--- a/source/blender/functions/tests/FN_multi_function_procedure_test.cc
+++ b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
@@ -32,7 +32,7 @@ TEST(multi_function_procedure, ConstantOutput)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor executor{"My Procedure", procedure};
+ MFProcedureExecutor executor{procedure};
MFParamsBuilder params{executor, 2};
MFContextBuilder context;
@@ -73,7 +73,7 @@ TEST(multi_function_procedure, SimpleTest)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor executor{"My Procedure", procedure};
+ MFProcedureExecutor executor{procedure};
MFParamsBuilder params{executor, 3};
MFContextBuilder context;
@@ -125,7 +125,7 @@ TEST(multi_function_procedure, BranchTest)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Condition Test", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params(procedure_fn, 5);
Array<int> values_a = {1, 5, 3, 6, 2};
@@ -167,7 +167,7 @@ TEST(multi_function_procedure, EvaluateOne)
builder.add_return();
builder.add_output_parameter(*var2);
- MFProcedureExecutor procedure_fn{"Evaluate One", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> values_out = {1, 2, 3, 4, 5};
@@ -239,7 +239,7 @@ TEST(multi_function_procedure, SimpleLoop)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Simple Loop", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> counts = {4, 3, 7, 6, 4};
@@ -295,7 +295,7 @@ TEST(multi_function_procedure, Vectors)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Vectors", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> v1 = {5, 2, 3};
@@ -359,7 +359,7 @@ TEST(multi_function_procedure, BufferReuse)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Buffer Reuse", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
Array<int> inputs = {4, 1, 6, 2, 3};
Array<int> results(5, -1);