GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
profiler.h
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2012-2025 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
40
41class OCTINTERP_API profiler
42{
43public:
44
45 // This is a utility class that can be used to call the enter/exit
46 // functions in a manner protected from stack unwinding.
47 template <typename T> class enter
48 {
49 private:
50
51 profiler& m_profiler;
52 std::string m_fcn;
53 bool m_enabled;
54
55 public:
56
57 enter (profiler& p, const T& t) : m_profiler (p)
58 {
59 // A profiling block cannot be active if the profiler is not
60 m_enabled = m_profiler.enabled ();
61
62 if (m_enabled)
63 {
64 m_fcn = t.profiler_name ();
65
66 // NOTE: The test f != "" must be kept to prevent a blank
67 // line showing up in profiler statistics. See bug
68 // #39524. The root cause is that the function name is
69 // not set for the recurring readline hook function.
70 if (m_fcn == "")
71 m_enabled = false; // Inactive profiling block
72 else
73 m_profiler.enter_function (m_fcn);
74 }
75 }
76
77 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (enter)
78
80 {
81 if (m_enabled)
82 m_profiler.exit_function (m_fcn);
83 }
84 };
85
86 profiler ();
87
88 OCTAVE_DISABLE_COPY_MOVE (profiler)
89
90 virtual ~profiler ();
91
92 bool enabled () const { return m_enabled; }
93 void set_active (bool);
94
95 void reset ();
96
97 octave_value get_flat () const;
98 octave_value get_hierarchical () const;
99
100private:
101
102 // One entry in the flat profile (i.e., a collection of data for a single
103 // function). This is filled in when building the flat profile from the
104 // hierarchical call tree.
105 struct stats
106 {
107 public:
108
109 stats ();
110
111 OCTAVE_DEFAULT_COPY_MOVE_DELETE (stats)
112
113 typedef std::set<octave_idx_type> function_set;
114
115 // Convert a function_set list to an Octave array of indices.
116 static octave_value function_set_value (const function_set&);
117
118 //--------
119
120 double m_time;
121 std::size_t m_calls;
122
123 bool m_recursive;
124
125 function_set m_parents;
126 function_set m_children;
127 };
128
129 typedef std::vector<stats> flat_profile;
130
131 // Store data for one node in the call-tree of the hierarchical profiler
132 // data we collect.
133 class tree_node
134 {
135 public:
136
137 tree_node (tree_node *, octave_idx_type);
138
139 virtual ~tree_node ();
140
141 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_node)
142
143 void add_time (double dt) { m_time += dt; }
144
145 // Enter a child function. It is created in the list of children if it
146 // wasn't already there. The now-active child node is returned.
147 tree_node * enter (octave_idx_type);
148
149 // Exit function. As a sanity-check, it is verified that the currently
150 // active function actually is the one handed in here. Returned is the
151 // then-active node, which is our parent.
152 tree_node * exit (octave_idx_type);
153
154 void build_flat (flat_profile&) const;
155
156 // Get the hierarchical profile for this node and its children. If total
157 // is set, accumulate total time of the subtree in that variable as
158 // additional return value.
159 octave_value get_hierarchical (double *total = nullptr) const;
160
161 private:
162
163 tree_node *m_parent;
164 octave_idx_type m_fcn_id;
165
166 typedef std::map<octave_idx_type, tree_node *> child_map;
167 child_map m_children;
168
169 // This is only time spent *directly* on this level, excluding children!
170 double m_time;
171
172 std::size_t m_calls;
173 };
174
175 // Each function we see in the profiler is given a unique index (which
176 // simply counts starting from 1). We thus have to map profiler-names to
177 // those indices. For all other stuff, we identify functions by their
178 // index.
179
180 typedef std::vector<std::string> function_set;
181 typedef std::map<std::string, octave_idx_type> fcn_index_map;
182
183 function_set m_known_functions;
184 fcn_index_map m_fcn_index;
185
186 bool m_enabled;
187
188 tree_node *m_call_tree;
189 tree_node *m_active_fcn;
190
191 // Store last timestamp we had, when the currently active function was
192 // called.
193 double m_last_time;
194
195 // These are private as only the unwind-protecting inner class enter
196 // should be allowed to call them.
197 void enter_function (const std::string&);
198 void exit_function (const std::string&);
199
200 // Query a timestamp, used for timing calls (obviously).
201 // This is not static because in the future, maybe we want a flag
202 // in the profiler or something to choose between cputime, wall-time,
203 // user-time, system-time, ...
204 double query_time () const;
205
206 // Add the time elapsed since last_time to the function we're currently in.
207 // This is called from two different positions, thus it is useful to have
208 // it as a separate function.
209 void add_current_time ();
210};
211
212OCTAVE_END_NAMESPACE(octave)
213
214#endif
enter(profiler &p, const T &t)
Definition profiler.h:57
bool enabled() const
Definition profiler.h:92
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn