Mercurial > octave-nkf
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!