Branch data Line data Source code
1 : : /* Timing variables for measuring compiler performance.
2 : : Copyright (C) 2000-2024 Free Software Foundation, Inc.
3 : : Contributed by Alex Samuel <samuel@codesourcery.com>
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it
8 : : under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : any later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT
13 : : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 : : or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 : : License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #ifndef GCC_TIMEVAR_H
22 : : #define GCC_TIMEVAR_H
23 : :
24 : : namespace json { class value; }
25 : :
26 : : /* Timing variables are used to measure elapsed time in various
27 : : portions of the compiler. Each measures elapsed user, system, and
28 : : wall-clock time, as appropriate to and supported by the host
29 : : system.
30 : :
31 : : Timing variables are defined using the DEFTIMEVAR macro in
32 : : timevar.def. Each has an enumeral identifier, used when referring
33 : : to the timing variable in code, and a character string name.
34 : :
35 : : Timing variables can be used in two ways:
36 : :
37 : : - On the timing stack, using timevar_push and timevar_pop.
38 : : Timing variables may be pushed onto the stack; elapsed time is
39 : : attributed to the topmost timing variable on the stack. When
40 : : another variable is pushed on, the previous topmost variable is
41 : : `paused' until the pushed variable is popped back off.
42 : :
43 : : - As a standalone timer, using timevar_start and timevar_stop.
44 : : All time elapsed between the two calls is attributed to the
45 : : variable.
46 : : */
47 : :
48 : : /* This structure stores the various varieties of time that can be
49 : : measured. Times are stored in nanoseconds. The time may be an
50 : : absolute time or a time difference; in the former case, the time
51 : : base is undefined, except that the difference between two times
52 : : produces a valid time difference. */
53 : :
54 : : struct timevar_time_def
55 : : {
56 : : /* User time in this process. */
57 : : uint64_t user;
58 : :
59 : : /* System time (if applicable for this host platform) in this process. */
60 : : uint64_t sys;
61 : :
62 : : /* Wall clock time. */
63 : : uint64_t wall;
64 : :
65 : : /* Garbage collector memory. */
66 : : size_t ggc_mem;
67 : : };
68 : :
69 : : /* An enumeration of timing variable identifiers. Constructed from
70 : : the contents of timevar.def. */
71 : :
72 : : #define DEFTIMEVAR(identifier__, name__) \
73 : : identifier__,
74 : : typedef enum
75 : : {
76 : : TV_NONE,
77 : : #include "timevar.def"
78 : : TIMEVAR_LAST
79 : : }
80 : : timevar_id_t;
81 : : #undef DEFTIMEVAR
82 : :
83 : : /* A class to hold all state relating to timing. */
84 : :
85 : : class timer;
86 : :
87 : : /* The singleton instance of timing state.
88 : :
89 : : This is non-NULL if timevars should be used. In GCC, this happens with
90 : : the -ftime-report flag. Hence this is NULL for the common,
91 : : needs-to-be-fast case, with an early reject happening for this being
92 : : NULL. */
93 : : extern timer *g_timer;
94 : :
95 : : /* Total amount of memory allocated by garbage collector. */
96 : : extern size_t timevar_ggc_mem_total;
97 : :
98 : : extern void timevar_init (void);
99 : : extern void timevar_start (timevar_id_t);
100 : : extern void timevar_stop (timevar_id_t);
101 : : extern bool timevar_cond_start (timevar_id_t);
102 : : extern void timevar_cond_stop (timevar_id_t, bool);
103 : :
104 : : /* The public (within GCC) interface for timing. */
105 : :
106 : : class timer
107 : : {
108 : : public:
109 : : timer ();
110 : : ~timer ();
111 : :
112 : : void start (timevar_id_t tv);
113 : : void stop (timevar_id_t tv);
114 : : void push (timevar_id_t tv);
115 : : void pop (timevar_id_t tv);
116 : : bool cond_start (timevar_id_t tv);
117 : : void cond_stop (timevar_id_t tv);
118 : :
119 : : void push_client_item (const char *item_name);
120 : : void pop_client_item ();
121 : :
122 : : void print (FILE *fp);
123 : : json::value *make_json () const;
124 : :
125 : : const char *get_topmost_item_name () const;
126 : :
127 : : private:
128 : : /* Private member functions. */
129 : : void validate_phases (FILE *fp) const;
130 : :
131 : : struct timevar_def;
132 : : void push_internal (struct timevar_def *tv);
133 : : void pop_internal ();
134 : : static void print_row (FILE *fp,
135 : : const timevar_time_def *total,
136 : : const char *name, const timevar_time_def &elapsed);
137 : : static bool all_zero (const timevar_time_def &elapsed);
138 : :
139 : : private:
140 : : typedef hash_map<timevar_def *, timevar_time_def> child_map_t;
141 : :
142 : : /* Private type: a timing variable. */
143 : : struct timevar_def
144 : : {
145 : : json::value *make_json () const;
146 : :
147 : : /* Elapsed time for this variable. */
148 : : struct timevar_time_def elapsed;
149 : :
150 : : /* If this variable is timed independently of the timing stack,
151 : : using timevar_start, this contains the start time. */
152 : : struct timevar_time_def start_time;
153 : :
154 : : /* The name of this timing variable. */
155 : : const char *name;
156 : :
157 : : /* Nonzero if this timing variable is running as a standalone
158 : : timer. */
159 : : unsigned standalone : 1;
160 : :
161 : : /* Nonzero if this timing variable was ever started or pushed onto
162 : : the timing stack. */
163 : : unsigned used : 1;
164 : :
165 : : child_map_t *children;
166 : : };
167 : :
168 : : /* Private type: an element on the timing stack
169 : : Elapsed time is attributed to the topmost timing variable on the
170 : : stack. */
171 : : struct timevar_stack_def
172 : : {
173 : : /* The timing variable at this stack level. */
174 : : struct timevar_def *timevar;
175 : :
176 : : /* The next lower timing variable context in the stack. */
177 : : struct timevar_stack_def *next;
178 : : };
179 : :
180 : : /* A class for managing a collection of named timing items, for use
181 : : e.g. by libgccjit for timing client code. This class is declared
182 : : inside timevar.cc to avoid everything using timevar.h
183 : : from needing vec and hash_map. */
184 : : class named_items;
185 : :
186 : : private:
187 : :
188 : : /* Data members (all private). */
189 : :
190 : : /* Declared timing variables. Constructed from the contents of
191 : : timevar.def. */
192 : : timevar_def m_timevars[TIMEVAR_LAST];
193 : :
194 : : /* The top of the timing stack. */
195 : : timevar_stack_def *m_stack;
196 : :
197 : : /* A list of unused (i.e. allocated and subsequently popped)
198 : : timevar_stack_def instances. */
199 : : timevar_stack_def *m_unused_stack_instances;
200 : :
201 : : /* The time at which the topmost element on the timing stack was
202 : : pushed. Time elapsed since then is attributed to the topmost
203 : : element. */
204 : : timevar_time_def m_start_time;
205 : :
206 : : /* If non-NULL, for use when timing libgccjit's client code. */
207 : : named_items *m_jit_client_items;
208 : :
209 : : friend class named_items;
210 : : };
211 : :
212 : : /* Provided for backward compatibility. */
213 : : inline void
214 : 14885966138 : timevar_push (timevar_id_t tv)
215 : : {
216 : 14885966138 : if (g_timer)
217 : 594451 : g_timer->push (tv);
218 : 14885966138 : }
219 : :
220 : : inline void
221 : 14885964646 : timevar_pop (timevar_id_t tv)
222 : : {
223 : 14885964646 : if (g_timer)
224 : 594451 : g_timer->pop (tv);
225 : 14885964646 : }
226 : :
227 : : // This is a simple timevar wrapper class that pushes a timevar in its
228 : : // constructor and pops the timevar in its destructor.
229 : : class auto_timevar
230 : : {
231 : : public:
232 : 33202004 : auto_timevar (timer *t, timevar_id_t tv)
233 : 33202004 : : m_timer (t),
234 : 33202004 : m_tv (tv)
235 : : {
236 : 33202004 : if (m_timer)
237 : 1604 : m_timer->push (m_tv);
238 : : }
239 : :
240 : 2280242986 : explicit auto_timevar (timevar_id_t tv)
241 : 2280242986 : : m_timer (g_timer)
242 : 2280242986 : , m_tv (tv)
243 : : {
244 : 2280242986 : if (m_timer)
245 : 408 : m_timer->push (m_tv);
246 : 2280242986 : }
247 : :
248 : 2313406962 : ~auto_timevar ()
249 : : {
250 : 2313406962 : if (m_timer)
251 : 2012 : m_timer->pop (m_tv);
252 : 2313406962 : }
253 : :
254 : : // Disallow copies.
255 : : auto_timevar (const auto_timevar &) = delete;
256 : :
257 : : private:
258 : : timer *m_timer;
259 : : timevar_id_t m_tv;
260 : : };
261 : :
262 : : // As above, but use cond_start/stop.
263 : : class auto_cond_timevar
264 : : {
265 : : public:
266 : : auto_cond_timevar (timer *t, timevar_id_t tv)
267 : : : m_timer (t),
268 : : m_tv (tv)
269 : : {
270 : : start ();
271 : : }
272 : :
273 : 8155778601 : explicit auto_cond_timevar (timevar_id_t tv)
274 : 8155778601 : : m_timer (g_timer)
275 : 8155778601 : , m_tv (tv)
276 : : {
277 : 8155778601 : start ();
278 : 723795869 : }
279 : :
280 : 8155766844 : ~auto_cond_timevar ()
281 : : {
282 : 8155766844 : if (m_timer && !already_running)
283 : 59396 : m_timer->cond_stop (m_tv);
284 : 8155766844 : }
285 : :
286 : : // Disallow copies.
287 : : auto_cond_timevar (const auto_cond_timevar &) = delete;
288 : :
289 : : private:
290 : 8155778601 : void start()
291 : : {
292 : 8155778601 : if (m_timer)
293 : 81216 : already_running = m_timer->cond_start (m_tv);
294 : : else
295 : 8155697385 : already_running = false;
296 : 8155778601 : }
297 : :
298 : : timer *m_timer;
299 : : timevar_id_t m_tv;
300 : : bool already_running;
301 : : };
302 : :
303 : : extern void print_time (const char *, long);
304 : :
305 : : #endif /* ! GCC_TIMEVAR_H */
|