GNU Octave  3.8.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) 2012-2013 Daniel Kraft
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if !defined (octave_profiler_h)
24 #define octave_profiler_h 1
25 
26 #include <cstddef>
27 #include <map>
28 #include <set>
29 #include <string>
30 #include <vector>
31 
32 class octave_value;
33 
34 class
37 {
38 public:
39 
40  // This is a utility class that can be used to call the enter/exit
41  // functions in a manner protected from stack unwinding.
42  class enter
43  {
44  private:
45 
47  std::string fcn;
48 
49  public:
50 
51  enter (profile_data_accumulator&, const std::string&);
52  virtual ~enter (void);
53 
54  private:
55 
56  // No copying!
57  enter (const enter&);
58  enter& operator = (const enter&);
59  };
60 
62  virtual ~profile_data_accumulator ();
63 
64  bool is_active (void) const { return enabled; }
65  void set_active (bool);
66 
67  void reset (void);
68 
69  octave_value get_flat (void) const;
70  octave_value get_hierarchical (void) const;
71 
72 private:
73 
74  // One entry in the flat profile (i.e., a collection of data for a single
75  // function). This is filled in when building the flat profile from the
76  // hierarchical call tree.
77  struct stats
78  {
79  stats ();
80 
81  double time;
82  unsigned calls;
83 
84  bool recursive;
85 
86  typedef std::set<octave_idx_type> function_set;
89 
90  // Convert a function_set list to an Octave array of indices.
91  static octave_value function_set_value (const function_set&);
92  };
93 
94  typedef std::vector<stats> flat_profile;
95 
96  // Store data for one node in the call-tree of the hierarchical profiler
97  // data we collect.
98  class tree_node
99  {
100  public:
101 
103  virtual ~tree_node ();
104 
105  void add_time (double dt) { time += dt; }
106 
107  // Enter a child function. It is created in the list of children if it
108  // wasn't already there. The now-active child node is returned.
110 
111  // Exit function. As a sanity-check, it is verified that the currently
112  // active function actually is the one handed in here. Returned is the
113  // then-active node, which is our parent.
114  tree_node* exit (octave_idx_type);
115 
116  void build_flat (flat_profile&) const;
117 
118  // Get the hierarchical profile for this node and its children. If total
119  // is set, accumulate total time of the subtree in that variable as
120  // additional return value.
121  octave_value get_hierarchical (double* total = 0) const;
122 
123  private:
124 
127 
128  typedef std::map<octave_idx_type, tree_node*> child_map;
130 
131  // This is only time spent *directly* on this level, excluding children!
132  double time;
133 
134  unsigned calls;
135 
136  // No copying!
137  tree_node (const tree_node&);
138  tree_node& operator = (const tree_node&);
139  };
140 
141  // Each function we see in the profiler is given a unique index (which
142  // simply counts starting from 1). We thus have to map profiler-names to
143  // those indices. For all other stuff, we identify functions by their index.
144 
145  typedef std::vector<std::string> function_set;
146  typedef std::map<std::string, octave_idx_type> fcn_index_map;
147 
148  function_set known_functions;
149  fcn_index_map fcn_index;
150 
151  bool enabled;
152 
155 
156  // Store last timestamp we had, when the currently active function was called.
157  double last_time;
158 
159  // These are private as only the unwind-protecting inner class enter
160  // should be allowed to call them.
161  void enter_function (const std::string&);
162  void exit_function (const std::string&);
163 
164  // Query a timestamp, used for timing calls (obviously).
165  // This is not static because in the future, maybe we want a flag
166  // in the profiler or something to choose between cputime, wall-time,
167  // user-time, system-time, ...
168  double query_time () const;
169 
170  // Add the time elapsed since last_time to the function we're currently in.
171  // This is called from two different positions, thus it is useful to have
172  // it as a seperate function.
173  void add_current_time (void);
174 
175  // No copying!
178 };
179 
180 // The instance used.
182 
183 // Helper macro to profile a block of code.
184 #define BEGIN_PROFILER_BLOCK(name) \
185  { \
186  profile_data_accumulator::enter pe (profiler, (name));
187 #define END_PROFILER_BLOCK \
188  }
189 
190 #endif