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