[Bf-blender-cvs] [6ee2abde82e] master: Functions: use static names for multi-functions

Jacques Lucke noreply at git.blender.org
Sun Nov 21 12:48:19 CET 2021


Commit: 6ee2abde82ef121cd6e927995053ac33afdbb438
Author: Jacques Lucke
Date:   Sun Nov 21 12:37:04 2021 +0100
Branches: master
https://developer.blender.org/rB6ee2abde82ef121cd6e927995053ac33afdbb438

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.

===================================================================

M	source/blender/functions/FN_multi_function.hh
M	source/blender/functions/FN_multi_function_builder.hh
M	source/blender/functions/FN_multi_function_procedure_executor.hh
M	source/blender/functions/FN_multi_function_signature.hh
M	source/blender/functions/intern/field.cc
M	source/blender/functions/intern/multi_function.cc
M	source/blender/functions/intern/multi_function_builder.cc
M	source/blender/functions/intern/multi_function_procedure.cc
M	source/blender/functions/intern/multi_function_procedure_executor.cc
M	source/blender/functions/tests/FN_multi_function_procedure_test.cc
M	source/blender/nodes/intern/type_conversions.cc
M	source/blender/nodes/shader/nodes/node_shader_math.cc
M	source/blender/nodes/shader/nodes/node_shader_vector_math.cc

===================================================================

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

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list