changeset 19361:91cd85a75705 gui-release

Reduce profiling overhead using inlining and templates. * profiler.cc (profile_data_accumulator::enter::enter): Remove function. * profiler.h: Make class "enter" a templated class. Have enter constructor check whether profiling is active before calling the expensive profiler_name() function. Redefine BEGIN_PROFILER_BLOCK macro to call profile_data_accumulator::enter with a classname argument to template. * ov-builtin.cc (octave_builtin::do_multi_index_op): Use new BEGIN_PROFILER_BLOCK macro. * ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Use new BEGIN_PROFILER_BLOCK macro. * ov-usr-fcn.cc (octave_user_script::do_multi_index_op, octave_user_function::do_multi_index_op): Use new BEGIN_PROFILER_BLOCK macro. * pt-binop.cc (tree_binary_expression::rvalue1): Use new BEGIN_PROFILER_BLOCK macro. * pt-binop.h (profiler_name): New function to return profiler name for class tree_binary_expression. * pt-unop.cc (tree_prefix_expression::rvalue1, tree_postfix_expression::rvalue1): Use new BEGIN_PROFILER_BLOCK macro. * pt-binop.h (profiler_name): New function to return profiler name for class tree_prefix_expression and tree_postfix_expression.
author Julien Bect <julien.bect@supelec.fr>
date Mon, 23 Jun 2014 18:46:32 +0200
parents 2b708273548d
children cbc838b3020c cd2a75e5cd6e
files libinterp/corefcn/profiler.cc libinterp/corefcn/profiler.h libinterp/octave-value/ov-builtin.cc libinterp/octave-value/ov-mex-fcn.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/pt-binop.cc libinterp/parse-tree/pt-binop.h libinterp/parse-tree/pt-unop.cc libinterp/parse-tree/pt-unop.h
diffstat 9 files changed, 57 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/profiler.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/corefcn/profiler.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -1,5 +1,6 @@
 /*
 
+Copyright (C) 2014 Julien Bect
 Copyright (C) 2012-2013 Daniel Kraft
 
 This file is part of Octave.
@@ -32,29 +33,6 @@
 #include "pager.h"
 #include "profiler.h"
 
-profile_data_accumulator::enter::enter (profile_data_accumulator& a,
-                                        const std::string& f)
-  : acc (a)
-{
-  // FIXME: Add test for f != "" to prevent a blank line showing up
-  //        in profiler statistics.  See bug #39524.  The root cause
-  //        is that the function name is not set for the recurring readline
-  //        hook function.
-  if (acc.is_active () && f != "")
-    {
-      fcn = f;
-      acc.enter_function (fcn);
-    }
-  else
-    fcn = "";
-}
-
-profile_data_accumulator::enter::~enter ()
-{
-  if (fcn != "")
-    acc.exit_function (fcn);
-}
-
 profile_data_accumulator::stats::stats ()
   : time (0.0), calls (0), recursive (false),
     parents (), children ()
--- a/libinterp/corefcn/profiler.h	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/corefcn/profiler.h	Mon Jun 23 18:46:32 2014 +0200
@@ -1,5 +1,6 @@
 /*
 
+Copyright (C) 2014 Julien Bect
 Copyright (C) 2012-2013 Daniel Kraft
 
 This file is part of Octave.
@@ -39,17 +40,40 @@
 
   // This is a utility class that can be used to call the enter/exit
   // functions in a manner protected from stack unwinding.
-  class enter
+  template<class T> class enter
   {
   private:
 
     profile_data_accumulator& acc;
     std::string fcn;
+    bool is_active;
 
   public:
 
-    enter (profile_data_accumulator&, const std::string&);
-    virtual ~enter (void);
+    enter (profile_data_accumulator& a, const T& t) : acc (a)
+    {
+      // A profiling block cannot be active if the profiler is not
+      is_active = acc.is_active ();
+
+      if (is_active)
+        {
+          fcn = t.profiler_name ();
+
+          // NOTE: The test f != "" must be kept to prevent a blank line showing
+          //  up in profiler statistics.  See bug #39524.  The root cause is that
+          //  the function name is not set for the recurring readline hook function.
+          if (fcn == "")
+            is_active = false;  // Inactive profiling block
+          else
+            acc.enter_function (fcn);
+        }
+    }
+
+    ~enter ()
+    {
+      if (is_active)
+        acc.exit_function (fcn);
+    }
 
   private:
 
@@ -181,10 +205,12 @@
 extern OCTINTERP_API profile_data_accumulator profiler;
 
 // Helper macro to profile a block of code.
-#define BEGIN_PROFILER_BLOCK(name) \
+
+#define BEGIN_PROFILER_BLOCK(classname) \
   { \
-    profile_data_accumulator::enter pe (profiler, (name));
+    profile_data_accumulator::enter<classname> pe (profiler, *this);
+
 #define END_PROFILER_BLOCK \
-  }
+  }  // end of block => call pe's destructor
 
 #endif
--- a/libinterp/octave-value/ov-builtin.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/octave-value/ov-builtin.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -127,7 +127,7 @@
 
       try
         {
-          BEGIN_PROFILER_BLOCK (profiler_name ())
+          BEGIN_PROFILER_BLOCK (octave_builtin)
 
           retval = (*f) (args, nargout);
           // Do not allow null values to be returned from functions.
--- a/libinterp/octave-value/ov-mex-fcn.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -148,8 +148,10 @@
 
       try
         {
-          BEGIN_PROFILER_BLOCK (profiler_name ())
+          BEGIN_PROFILER_BLOCK (octave_mex_function)
+
           retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this);
+
           END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -149,8 +149,10 @@
                   frame.protect_var (tree_evaluator::statement_context);
                   tree_evaluator::statement_context = tree_evaluator::script;
 
-                  BEGIN_PROFILER_BLOCK (profiler_name ())
+                  BEGIN_PROFILER_BLOCK (octave_user_script)
+
                   cmd_list->accept (*current_evaluator);
+
                   END_PROFILER_BLOCK
 
                   if (tree_return_command::returning)
@@ -574,7 +576,7 @@
   frame.protect_var (tree_evaluator::statement_context);
   tree_evaluator::statement_context = tree_evaluator::function;
 
-  BEGIN_PROFILER_BLOCK (profiler_name ())
+  BEGIN_PROFILER_BLOCK (octave_user_function)
 
   if (is_special_expr ())
     {
--- a/libinterp/parse-tree/pt-binop.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/parse-tree/pt-binop.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -135,7 +135,7 @@
 
           if (! error_state && b.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("binary " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_binary_expression)
 
               // Note: The profiler does not catch the braindead
               // short-circuit evaluation code above, but that should be
--- a/libinterp/parse-tree/pt-binop.h	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/parse-tree/pt-binop.h	Mon Jun 23 18:46:32 2014 +0200
@@ -100,6 +100,9 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const { return "binary " + oper (); }
+
+
 protected:
 
   // The operands for the expression.
--- a/libinterp/parse-tree/pt-unop.cc	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/parse-tree/pt-unop.cc	Mon Jun 23 18:46:32 2014 +0200
@@ -73,8 +73,8 @@
 
           if (! error_state)
             {
-              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
-
+              BEGIN_PROFILER_BLOCK (tree_prefix_expression)
+              
               ref.do_unary_op (etype);
 
               if (! error_state)
@@ -89,7 +89,7 @@
 
           if (! error_state && val.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_prefix_expression)
 
               // Attempt to do the operation in-place if it is unshared
               // (a temporary expression).
@@ -162,8 +162,10 @@
             {
               retval = ref.value ();
 
-              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_postfix_expression)
+
               ref.do_unary_op (etype);
+
               END_PROFILER_BLOCK
             }
         }
@@ -173,7 +175,7 @@
 
           if (! error_state && val.is_defined ())
             {
-              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+              BEGIN_PROFILER_BLOCK (tree_postfix_expression)
 
               retval = ::do_unary_op (etype, val);
 
--- a/libinterp/parse-tree/pt-unop.h	Sat Nov 08 16:45:13 2014 +0100
+++ b/libinterp/parse-tree/pt-unop.h	Mon Jun 23 18:46:32 2014 +0200
@@ -108,6 +108,9 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const { return "prefix " + oper (); }
+
+
 private:
 
   // No copying!
@@ -145,6 +148,8 @@
 
   void accept (tree_walker& tw);
 
+  std::string profiler_name (void) const { return "postfix " + oper (); }
+
 private:
 
   // No copying!