1 /* Timing variables for measuring compiler performance.
3 Copyright (C) 2000, 2002, 2004, 2006, 2009-2015, 2018 Free Software
6 Contributed by Alex Samuel <samuel@codesourcery.com>
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #define _(msgid) gettext (msgid)
32 # include <sys/time.h>
35 #ifdef HAVE_SYS_TIMES_H
36 # include <sys/times.h>
38 #ifdef HAVE_SYS_RESOURCE_H
39 # include <sys/resource.h>
46 #ifndef HAVE_STRUCT_TMS
56 /* Calculation of scale factor to convert ticks to microseconds.
57 We mustn't use CLOCKS_PER_SEC except with clock(). */
58 #if HAVE_SYSCONF && defined _SC_CLK_TCK
59 # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
61 # define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
63 # define TICKS_PER_SECOND HZ /* traditional UNIX */
65 # define TICKS_PER_SECOND 100 /* often the correct value */
68 /* Prefer times to getrusage to clock (each gives successively less
70 #if defined HAVE_TIMES
72 # define HAVE_USER_TIME
73 # define HAVE_SYS_TIME
74 # define HAVE_WALL_TIME
75 #elif defined HAVE_GETRUSAGE
76 # define USE_GETRUSAGE
77 # define HAVE_USER_TIME
78 # define HAVE_SYS_TIME
79 #elif defined HAVE_CLOCK
81 # define HAVE_USER_TIME
84 #if defined USE_TIMES && !defined HAVE_DECL_TIMES
85 clock_t times (struct tms
*);
86 #elif defined USE_GETRUSAGE && !defined HAVE_DECL_GETRUSAGE
87 int getrusage (int, struct rusage
*);
88 #elif defined USE_CLOCK && !defined HAVE_DECL_CLOCK
92 /* libc is very likely to have snuck a call to sysconf() into one of
93 the underlying constants, and that can be very slow, so we have to
94 precompute them. Whose wonderful idea was it to make all those
95 _constants_ variable at run time, anyway? */
97 static float ticks_to_msec
;
98 # define TICKS_TO_MSEC (1.0 / TICKS_PER_SECOND)
99 #elif defined USE_CLOCK
100 static float clocks_to_msec
;
101 # define CLOCKS_TO_MSEC (1.0 / CLOCKS_PER_SEC)
106 /* See timevar.h for an explanation of timing variables. */
108 int timevar_enabled
= 0;
110 /* A timing variable. */
114 /* Elapsed time for this variable. */
115 struct timevar_time_def elapsed
;
117 /* If this variable is timed independently of the timing stack,
118 using timevar_start, this contains the start time. */
119 struct timevar_time_def start_time
;
121 /* The name of this timing variable. */
124 /* Non-zero if this timing variable is running as a standalone
126 unsigned standalone
: 1;
128 /* Non-zero if this timing variable was ever started or pushed onto
133 /* An element on the timing stack. Elapsed time is attributed to the
134 topmost timing variable on the stack. */
136 struct timevar_stack_def
138 /* The timing variable at this stack level. */
139 struct timevar_def
*timevar
;
141 /* The next lower timing variable context in the stack. */
142 struct timevar_stack_def
*next
;
145 /* Declared timing variables. Constructed from the contents of
147 static struct timevar_def timevars
[TIMEVAR_LAST
];
149 /* The top of the timing stack. */
150 static struct timevar_stack_def
*stack
;
152 /* A list of unused (i.e. allocated and subsequently popped)
153 timevar_stack_def instances. */
154 static struct timevar_stack_def
*unused_stack_instances
;
156 /* The time at which the topmost element on the timing stack was
157 pushed. Time elapsed since then is attributed to the topmost
159 static struct timevar_time_def start_time
;
161 /* Fill the current times into TIME. The definition of this function
162 also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
163 HAVE_WALL_TIME macros. */
166 set_to_current_time (struct timevar_time_def
*now
)
172 if (!timevar_enabled
)
178 now
->wall
= times (&tms
) * ticks_to_msec
;
179 now
->user
= (tms
.tms_utime
+ tms
.tms_cutime
) * ticks_to_msec
;
180 now
->sys
= (tms
.tms_stime
+ tms
.tms_cstime
) * ticks_to_msec
;
181 #elif defined USE_GETRUSAGE
182 struct rusage rusage
;
183 getrusage (RUSAGE_CHILDREN
, &rusage
);
184 now
->user
= rusage
.ru_utime
.tv_sec
+ rusage
.ru_utime
.tv_usec
* 1e-6;
185 now
->sys
= rusage
.ru_stime
.tv_sec
+ rusage
.ru_stime
.tv_usec
* 1e-6;
186 #elif defined USE_CLOCK
187 now
->user
= clock () * clocks_to_msec
;
192 /* Return the current time. */
194 static struct timevar_time_def
195 get_current_time (void)
197 struct timevar_time_def now
;
198 set_to_current_time (&now
);
202 /* Add the difference between STOP and START to TIMER. */
205 timevar_accumulate (struct timevar_time_def
*timer
,
206 const struct timevar_time_def
*start
,
207 const struct timevar_time_def
*stop
)
209 timer
->user
+= stop
->user
- start
->user
;
210 timer
->sys
+= stop
->sys
- start
->sys
;
211 timer
->wall
+= stop
->wall
- start
->wall
;
217 if (!timevar_enabled
)
220 /* Zero all elapsed times. */
221 memset ((void *) timevars
, 0, sizeof (timevars
));
223 /* Initialize the names of timing variables. */
224 #define DEFTIMEVAR(identifier__, name__) \
225 timevars[identifier__].name = name__;
226 #include "timevar.def"
229 #if defined USE_TIMES
230 ticks_to_msec
= TICKS_TO_MSEC
;
231 #elif defined USE_CLOCK
232 clocks_to_msec
= CLOCKS_TO_MSEC
;
237 timevar_push (timevar_id_t timevar
)
239 if (!timevar_enabled
)
242 struct timevar_def
*tv
= &timevars
[timevar
];
244 /* Mark this timing variable as used. */
247 /* Can't push a standalone timer. */
251 /* What time is it? */
252 struct timevar_time_def
const now
= get_current_time ();
254 /* If the stack isn't empty, attribute the current elapsed time to
255 the old topmost element. */
257 timevar_accumulate (&stack
->timevar
->elapsed
, &start_time
, &now
);
259 /* Reset the start time; from now on, time is attributed to
263 /* See if we have a previously-allocated stack instance. If so,
264 take it off the list. If not, malloc a new one. */
265 struct timevar_stack_def
*context
= NULL
;
266 if (unused_stack_instances
!= NULL
)
268 context
= unused_stack_instances
;
269 unused_stack_instances
= unused_stack_instances
->next
;
272 context
= (struct timevar_stack_def
*)
273 xmalloc (sizeof (struct timevar_stack_def
));
275 /* Fill it in and put it on the stack. */
276 context
->timevar
= tv
;
277 context
->next
= stack
;
282 timevar_pop (timevar_id_t timevar
)
284 if (!timevar_enabled
)
287 if (&timevars
[timevar
] != stack
->timevar
)
290 /* What time is it? */
291 struct timevar_time_def
const now
= get_current_time ();
293 /* Attribute the elapsed time to the element we're popping. */
294 struct timevar_stack_def
*popped
= stack
;
295 timevar_accumulate (&popped
->timevar
->elapsed
, &start_time
, &now
);
297 /* Reset the start time; from now on, time is attributed to the
298 element just exposed on the stack. */
301 /* Take the item off the stack. */
304 /* Don't delete the stack element; instead, add it to the list of
305 unused elements for later use. */
306 popped
->next
= unused_stack_instances
;
307 unused_stack_instances
= popped
;
311 timevar_start (timevar_id_t timevar
)
313 if (!timevar_enabled
)
316 struct timevar_def
*tv
= &timevars
[timevar
];
318 /* Mark this timing variable as used. */
321 /* Don't allow the same timing variable to be started more than
327 set_to_current_time (&tv
->start_time
);
331 timevar_stop (timevar_id_t timevar
)
333 if (!timevar_enabled
)
336 struct timevar_def
*tv
= &timevars
[timevar
];
338 /* TIMEVAR must have been started via timevar_start. */
342 struct timevar_time_def
const now
= get_current_time ();
343 timevar_accumulate (&tv
->elapsed
, &tv
->start_time
, &now
);
347 timevar_get (timevar_id_t timevar
,
348 struct timevar_time_def
*elapsed
)
350 struct timevar_def
*tv
= &timevars
[timevar
];
351 *elapsed
= tv
->elapsed
;
353 /* Is TIMEVAR currently running as a standalone timer? */
356 struct timevar_time_def
const now
= get_current_time ();
357 timevar_accumulate (elapsed
, &tv
->start_time
, &now
);
359 /* Or is TIMEVAR at the top of the timer stack? */
360 else if (stack
->timevar
== tv
)
362 struct timevar_time_def
const now
= get_current_time ();
363 timevar_accumulate (elapsed
, &start_time
, &now
);
368 timevar_print (FILE *fp
)
370 /* Only print stuff if we have some sort of time information. */
371 #if defined HAVE_USER_TIME || defined HAVE_SYS_TIME || defined HAVE_WALL_TIME
372 if (!timevar_enabled
)
375 /* Update timing information in case we're calling this from GDB. */
380 /* What time is it? */
381 struct timevar_time_def
const now
= get_current_time ();
383 /* If the stack isn't empty, attribute the current elapsed time to
384 the old topmost element. */
386 timevar_accumulate (&stack
->timevar
->elapsed
, &start_time
, &now
);
388 /* Reset the start time; from now on, time is attributed to
392 struct timevar_time_def
const* total
= &timevars
[tv_total
].elapsed
;
394 fputs (_("\nExecution times (seconds)\n"), fp
);
395 for (unsigned /* timevar_id_t */ id
= 0; id
< (unsigned) TIMEVAR_LAST
; ++id
)
397 struct timevar_def
*tv
= &timevars
[(timevar_id_t
) id
];
398 const float tiny
= 5e-3;
400 /* Don't print the total execution time here; that goes at the
402 if ((timevar_id_t
) id
== tv_total
)
405 /* Don't print timing variables that were never used. */
409 /* Don't print timing variables if we're going to get a row of
411 if (tv
->elapsed
.user
< tiny
412 && tv
->elapsed
.sys
< tiny
413 && tv
->elapsed
.wall
< tiny
)
416 /* The timing variable name. */
417 fprintf (fp
, " %-22s:", tv
->name
);
419 # ifdef HAVE_USER_TIME
420 /* Print user-mode time for this process. */
421 fprintf (fp
, "%7.2f (%2.0f%%) usr",
423 (total
->user
== 0 ? 0 : tv
->elapsed
.user
/ total
->user
) * 100);
426 # ifdef HAVE_SYS_TIME
427 /* Print system-mode time for this process. */
428 fprintf (fp
, "%7.2f (%2.0f%%) sys",
430 (total
->sys
== 0 ? 0 : tv
->elapsed
.sys
/ total
->sys
) * 100);
433 # ifdef HAVE_WALL_TIME
434 /* Print wall clock time elapsed. */
435 fprintf (fp
, "%7.2f (%2.0f%%) wall",
437 (total
->wall
== 0 ? 0 : tv
->elapsed
.wall
/ total
->wall
) * 100);
443 /* Print total time. */
444 fprintf (fp
, " %-22s:", timevars
[tv_total
].name
);
445 #ifdef HAVE_USER_TIME
446 fprintf (fp
, "%7.2f ", total
->user
);
449 fprintf (fp
, "%7.2f ", total
->sys
);
451 #ifdef HAVE_WALL_TIME
452 fprintf (fp
, "%7.2f\n", total
->wall
);
455 #endif /* defined HAVE_USER_TIME || defined HAVE_SYS_TIME || defined HAVE_WALL_TIME */