GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
profiler.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2014-2015 Julien Bect
4 Copyright (C) 2012-2015 Daniel Kraft
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if !defined (octave_profiler_h)
25 #define octave_profiler_h 1
26 
27 #include <cstddef>
28 #include <map>
29 #include <set>
30 #include <string>
31 #include <vector>
32 
33 class octave_value;
34 
35 class
38 {
39 public:
40 
41  // This is a utility class that can be used to call the enter/exit
42  // functions in a manner protected from stack unwinding.
43  template<class T> class enter
44  {
45  private:
46 
48  std::string fcn;
49  bool is_active;
50 
51  public:
52 
53  enter (profile_data_accumulator& a, const T& t) : acc (a)
54  {
55  // A profiling block cannot be active if the profiler is not
56  is_active = acc.is_active ();
57 
58  if (is_active)
59  {
60  fcn = t.profiler_name ();
61 
62  // NOTE: The test f != "" must be kept to prevent a blank line showing
63  // up in profiler statistics. See bug #39524. The root cause is that
64  // the function name is not set for the recurring readline hook function.
65  if (fcn == "")
66  is_active = false; // Inactive profiling block
67  else
68  acc.enter_function (fcn);
69  }
70  }
71 
72  ~enter ()
73  {
74  if (is_active)
75  acc.exit_function (fcn);
76  }
77 
78  private:
79 
80  // No copying!
81  enter (const enter&);
82  enter& operator = (const enter&);
83  };
84 
86  virtual ~profile_data_accumulator ();
87 
88  bool is_active (void) const { return enabled; }
89  void set_active (bool);
90 
91  void reset (void);
92 
93  octave_value get_flat (void) const;
94  octave_value get_hierarchical (void) const;
95 
96 private:
97 
98  // One entry in the flat profile (i.e., a collection of data for a single
99  // function). This is filled in when building the flat profile from the
100  // hierarchical call tree.
101  struct stats
102  {
103  stats ();
104 
105  double time;
106  unsigned calls;
107 
108  bool recursive;
109 
110  typedef std::set<octave_idx_type> function_set;
111  function_set parents;
112  function_set children;
113 
114  // Convert a function_set list to an Octave array of indices.
115  static octave_value function_set_value (const function_set&);
116  };
117 
118  typedef std::vector<stats> flat_profile;
119 
120  // Store data for one node in the call-tree of the hierarchical profiler
121  // data we collect.
122  class tree_node
123  {
124  public:
125 
127  virtual ~tree_node ();
128 
129  void add_time (double dt) { time += dt; }
130 
131  // Enter a child function. It is created in the list of children if it
132  // wasn't already there. The now-active child node is returned.
134 
135  // Exit function. As a sanity-check, it is verified that the currently
136  // active function actually is the one handed in here. Returned is the
137  // then-active node, which is our parent.
138  tree_node* exit (octave_idx_type);
139 
140  void build_flat (flat_profile&) const;
141 
142  // Get the hierarchical profile for this node and its children. If total
143  // is set, accumulate total time of the subtree in that variable as
144  // additional return value.
145  octave_value get_hierarchical (double* total = 0) const;
146 
147  private:
148 
151 
152  typedef std::map<octave_idx_type, tree_node*> child_map;
153  child_map children;
154 
155  // This is only time spent *directly* on this level, excluding children!
156  double time;
157 
158  unsigned calls;
159 
160  // No copying!
161  tree_node (const tree_node&);
162  tree_node& operator = (const tree_node&);
163  };
164 
165  // Each function we see in the profiler is given a unique index (which
166  // simply counts starting from 1). We thus have to map profiler-names to
167  // those indices. For all other stuff, we identify functions by their index.
168 
169  typedef std::vector<std::string> function_set;
170  typedef std::map<std::string, octave_idx_type> fcn_index_map;
171 
172  function_set known_functions;
173  fcn_index_map fcn_index;
174 
175  bool enabled;
176 
179 
180  // Store last timestamp we had, when the currently active function was called.
181  double last_time;
182 
183  // These are private as only the unwind-protecting inner class enter
184  // should be allowed to call them.
185  void enter_function (const std::string&);
186  void exit_function (const std::string&);
187 
188  // Query a timestamp, used for timing calls (obviously).
189  // This is not static because in the future, maybe we want a flag
190  // in the profiler or something to choose between cputime, wall-time,
191  // user-time, system-time, ...
192  double query_time () const;
193 
194  // Add the time elapsed since last_time to the function we're currently in.
195  // This is called from two different positions, thus it is useful to have
196  // it as a seperate function.
197  void add_current_time (void);
198 
199  // No copying!
202 };
203 
204 // The instance used.
206 
207 // Helper macro to profile a block of code.
208 
209 #define BEGIN_PROFILER_BLOCK(classname) \
210  { \
211  profile_data_accumulator::enter<classname> pe (profiler, *this);
212 
213 #define END_PROFILER_BLOCK \
214  } // end of block => call pe's destructor
215 
216 #endif
function_set known_functions
Definition: profiler.h:172
std::map< std::string, octave_idx_type > fcn_index_map
Definition: profiler.h:170
enter(profile_data_accumulator &a, const T &t)
Definition: profiler.h:53
tree_node * call_tree
Definition: profiler.h:177
bool is_active(void) const
Definition: profiler.h:88
std::vector< std::string > function_set
Definition: profiler.h:169
#define OCTINTERP_API
Definition: mexproto.h:66
std::vector< stats > flat_profile
Definition: profiler.h:118
fcn_index_map fcn_index
Definition: profiler.h:173
void exit_function(const std::string &)
Definition: profiler.cc:240
std::set< octave_idx_type > function_set
Definition: profiler.h:110
OCTINTERP_API profile_data_accumulator profiler
Definition: profiler.cc:395
std::map< octave_idx_type, tree_node * > child_map
Definition: profiler.h:152
void enter_function(const std::string &)
Definition: profiler.cc:211
profile_data_accumulator & acc
Definition: profiler.h:47
tree_node * active_fcn
Definition: profiler.h:178