]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/timevar.c
c-decl.c: Mark strings for translation.
[thirdparty/gcc.git] / gcc / timevar.c
CommitLineData
2a9a326b
AS
1/* Timing variables for measuring compiler performance.
2 Copyright (C) 2000 Free Software Foundation, Inc.
3 Contributed by Alex Samuel <samuel@codesourcery.com>
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "config.h"
23#include "system.h"
24
25#ifdef HAVE_SYS_TIMES_H
26# include <sys/times.h>
27#endif
28
26026d38 29#include "flags.h"
2a9a326b
AS
30#include "timevar.h"
31
32/* See timevar.h for an explanation of timing variables. */
33
26026d38
AS
34/* This macro evaluates to non-zero if timing variables are enabled. */
35#define TIMEVAR_ENABLE (!quiet_flag)
36
2a9a326b
AS
37/* A timing variable. */
38
39struct timevar_def
40{
41 /* Elapsed time for this variable. */
42 struct timevar_time_def elapsed;
43
44 /* If this variable is timed independently of the timing stack,
45 using timevar_start, this contains the start time. */
46 struct timevar_time_def start_time;
47
26026d38
AS
48 /* The name of this timing variable. */
49 const char *name;
50
2a9a326b
AS
51 /* Non-zero if this timing variable is running as a standalone
52 timer. */
26026d38 53 unsigned standalone : 1;
2a9a326b 54
26026d38
AS
55 /* Non-zero if this timing variable was ever started or pushed onto
56 the timing stack. */
57 unsigned used : 1;
2a9a326b
AS
58};
59
60/* An element on the timing stack. Elapsed time is attributed to the
61 topmost timing variable on the stack. */
62
63struct timevar_stack_def
64{
65 /* The timing variable at this stack level. */
66 struct timevar_def *timevar;
67
68 /* The next lower timing variable context in the stack. */
69 struct timevar_stack_def *next;
70};
71
72/* Declared timing variables. Constructed from the contents of
73 timevar.def. */
74static struct timevar_def timevars[TIMEVAR_LAST];
75
76/* The top of the timing stack. */
77static struct timevar_stack_def *stack;
78
26026d38
AS
79/* A list of unused (i.e. allocated and subsequently popped)
80 timevar_stack_def instances. */
81static struct timevar_stack_def *unused_stack_instances;
82
2a9a326b
AS
83/* The time at which the topmost element on the timing stack was
84 pushed. Time elapsed since then is attributed to the topmost
85 element. */
86static struct timevar_time_def start_time;
87
88static void get_time
89 PARAMS ((struct timevar_time_def *));
90static void timevar_add
91 PARAMS ((struct timevar_time_def *, struct timevar_time_def *));
92static void timevar_accumulate
93 PARAMS ((struct timevar_time_def *, struct timevar_time_def *,
94 struct timevar_time_def *));
95
96/* Fill the current times into TIME. The definition of this function
97 also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
98 HAVA_WALL_TIME macros. */
99
100static void
26026d38
AS
101get_time (now)
102 struct timevar_time_def *now;
2a9a326b 103{
26026d38
AS
104 now->user = 0;
105 now->sys = 0;
106 now->wall = 0;
107
108 if (!TIMEVAR_ENABLE)
109 return;
2a9a326b
AS
110
111#ifdef __BEOS__
112 /* Nothing. */
113#else /* not BeOS */
114#if defined (_WIN32) && !defined (__CYGWIN__)
115 if (clock () >= 0)
26026d38 116 now->user = clock () * 1000;
2a9a326b
AS
117#define HAVE_USER_TIME
118
119#else /* not _WIN32 */
120#ifdef _SC_CLK_TCK
121 {
122 static int tick;
123 struct tms tms;
124 if (tick == 0)
125 tick = 1000000 / sysconf (_SC_CLK_TCK);
26026d38
AS
126 now->wall = times (&tms) * tick;
127 now->user = tms.tms_utime * tick;
128 now->sys = tms.tms_stime * tick;
2a9a326b
AS
129 }
130#define HAVE_USER_TIME
131#define HAVE_SYS_TIME
132#define HAVE_WALL_TIME
133
134#else
135#ifdef USG
136 {
137 struct tms tms;
138# if HAVE_SYSCONF && defined _SC_CLK_TCK
139# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
140# else
141# ifdef CLK_TCK
142# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
143# else
144# define TICKS_PER_SECOND HZ /* traditional UNIX */
145# endif
146# endif
26026d38
AS
147 now->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
148 now->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
149 now->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
2a9a326b
AS
150 }
151#define HAVE_USER_TIME
152#define HAVE_SYS_TIME
153#define HAVE_WALL_TIME
154
155#else
156#ifndef VMS
157 {
158 struct rusage rusage;
159 getrusage (0, &rusage);
26026d38 160 now->user
2a9a326b 161 = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
26026d38 162 now->sys
2a9a326b
AS
163 = rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
164 }
165#define HAVE_USER_TIME
166#define HAVE_SYS_TIME
167
168#else /* VMS */
169 {
170 struct
171 {
172 int proc_user_time;
173 int proc_system_time;
174 int child_user_time;
175 int child_system_time;
176 } vms_times;
26026d38
AS
177 now->wall = times ((void *) &vms_times) * 10000;
178 now->user = vms_times.proc_user_time * 10000;
179 now->sys = vms_times.proc_system_time * 10000;
2a9a326b
AS
180 }
181#define HAVE_USER_TIME
182#define HAVE_SYS_TIME
183#define HAVE_WALL_TIME
184
185#endif /* VMS */
186#endif /* USG */
187#endif /* _SC_CLK_TCK */
188#endif /* _WIN32 */
189#endif /* __BEOS__ */
190}
191
192/* Add ELAPSED to TIMER. */
193
194static void
195timevar_add (timer, elapsed)
196 struct timevar_time_def *timer;
197 struct timevar_time_def *elapsed;
198{
199 timer->user += elapsed->user;
200 timer->sys += elapsed->sys;
201 timer->wall += elapsed->wall;
202}
203
204/* Add the difference between STOP_TIME and START_TIME to TIMER. */
205
206static void
207timevar_accumulate (timer, start_time, stop_time)
208 struct timevar_time_def *timer;
209 struct timevar_time_def *start_time;
210 struct timevar_time_def *stop_time;
211{
212 timer->user += stop_time->user - start_time->user;
213 timer->sys += stop_time->sys - start_time->sys;
214 timer->wall += stop_time->wall - start_time->wall;
215}
216
217/* Initialize timing variables. */
218
219void
4fbe8d07 220init_timevar ()
2a9a326b 221{
26026d38
AS
222 if (!TIMEVAR_ENABLE)
223 return;
224
2a9a326b
AS
225 /* Zero all elapsed times. */
226 memset ((void *) timevars, 0, sizeof (timevars));
227
228 /* Initialize the names of timing variables. */
229#define DEFTIMEVAR(identifer__, name__) \
230 timevars[identifer__].name = name__;
231#include "timevar.def"
232#undef DEFTIMEVAR
233}
234
235/* Push TIMEVAR onto the timing stack. No further elapsed time is
236 attributed to the previous topmost timing variable on the stack;
237 subsequent elapsed time is attributed to TIMEVAR, until it is
238 popped or another element is pushed on top.
239
240 TIMEVAR cannot be running as a standalone timer. */
241
242void
243timevar_push (timevar)
244 timevar_id_t timevar;
245{
246 struct timevar_def *tv = &timevars[timevar];
247 struct timevar_stack_def *context;
248 struct timevar_time_def now;
249
26026d38
AS
250 if (!TIMEVAR_ENABLE)
251 return;
252
253 /* Mark this timing variable as used. */
254 tv->used = 1;
255
2a9a326b
AS
256 /* Can't push a standalone timer. */
257 if (tv->standalone)
258 abort ();
259
260 /* What time is it? */
261 get_time (&now);
262
263 /* If the stack isn't empty, attribute the current elapsed time to
264 the old topmost element. */
265 if (stack)
266 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
267
268 /* Reset the start time; from now on, time is attributed to
269 TIMEVAR. */
270 start_time = now;
271
26026d38
AS
272 /* See if we have a previously-allocated stack instance. If so,
273 take it off the list. If not, malloc a new one. */
274 if (unused_stack_instances != NULL)
275 {
276 context = unused_stack_instances;
277 unused_stack_instances = unused_stack_instances->next;
278 }
279 else
280 context = (struct timevar_stack_def *)
281 xmalloc (sizeof (struct timevar_stack_def));
282
283 /* Fill it in and put it on the stack. */
2a9a326b
AS
284 context->timevar = tv;
285 context->next = stack;
286 stack = context;
287}
288
289/* Pop the topmost timing variable element off the timing stack. The
290 popped variable must be TIMEVAR. Elapsed time since the that
291 element was pushed on, or since it was last exposed on top of the
292 stack when the element above it was popped off, is credited to that
293 timing variable. */
294
295void
296timevar_pop (timevar)
297 timevar_id_t timevar;
298{
299 struct timevar_time_def now;
26026d38
AS
300 struct timevar_stack_def *popped = stack;
301
302 if (!TIMEVAR_ENABLE)
303 return;
2a9a326b
AS
304
305 if (&timevars[timevar] != stack->timevar)
306 abort ();
307
308 /* What time is it? */
309 get_time (&now);
310
311 /* Attribute the elapsed time to the element we're popping. */
26026d38 312 timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
2a9a326b
AS
313
314 /* Reset the start time; from now on, time is attributed to the
315 element just exposed on the stack. */
316 start_time = now;
317
26026d38
AS
318 /* Take the item off the stack. */
319 stack = stack->next;
320
321 /* Don't delete the stack element; instead, add it to the list of
322 unused elements for later use. */
323 popped->next = unused_stack_instances;
324 unused_stack_instances = popped;
2a9a326b
AS
325}
326
327/* Start timing TIMEVAR independently of the timing stack. Elapsed
328 time until timevar_stop is called for the same timing variable is
329 attributed to TIMEVAR. */
330
331void
332timevar_start (timevar)
333 timevar_id_t timevar;
334{
335 struct timevar_def *tv = &timevars[timevar];
336
26026d38
AS
337 if (!TIMEVAR_ENABLE)
338 return;
339
340 /* Mark this timing variable as used. */
341 tv->used = 1;
342
2a9a326b
AS
343 /* Don't allow the same timing variable to be started more than
344 once. */
345 if (tv->standalone)
346 abort ();
347 tv->standalone = 1;
348
349 get_time (&tv->start_time);
350}
351
352/* Stop timing TIMEVAR. Time elapsed since timevar_start was called
353 is attributed to it. */
354
355void
356timevar_stop (timevar)
357 timevar_id_t timevar;
358{
359 struct timevar_def *tv = &timevars[timevar];
360 struct timevar_time_def now;
361
26026d38
AS
362 if (!TIMEVAR_ENABLE)
363 return;
364
2a9a326b
AS
365 /* TIMEVAR must have been started via timevar_start. */
366 if (!tv->standalone)
367 abort ();
368
369 get_time (&now);
370 timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
371}
372
373/* Fill the elapsed time for TIMEVAR into ELAPSED. Returns
374 update-to-date information even if TIMEVAR is currently running. */
375
376void
377timevar_get (timevar, elapsed)
378 timevar_id_t timevar;
379 struct timevar_time_def *elapsed;
380{
381 struct timevar_def *tv = &timevars[timevar];
382
383 *elapsed = tv->elapsed;
384
385 /* Is TIMEVAR currently running as a standalone timer? */
386 if (tv->standalone)
387 /* Add the time elapsed since the it was started. */
388 timevar_add (elapsed, &tv->start_time);
389
390 /* Is TIMEVAR at the top of the timer stack? */
391 if (stack->timevar == tv)
392 /* Add the elapsed time since it was pushed. */
393 timevar_add (elapsed, &start_time);
394}
395
396/* Summarize timing variables to FP. The timing variable TV_TOTAL has
397 a special meaning -- it's considered to be the total elapsed time,
398 for normalizing the others, and is displayed last. */
399
400void
401timevar_print (fp)
402 FILE *fp;
403{
404 /* Only print stuff if we have some sort of time information. */
405#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
406 timevar_id_t id;
407 struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
ea11ca7e 408 struct timevar_time_def now;
2a9a326b 409
26026d38
AS
410 if (!TIMEVAR_ENABLE)
411 return;
412
ea11ca7e
JM
413 /* Update timing information in case we're calling this from GDB. */
414
415 if (fp == 0)
416 fp = stderr;
417
418 /* What time is it? */
419 get_time (&now);
420
421 /* If the stack isn't empty, attribute the current elapsed time to
422 the old topmost element. */
423 if (stack)
424 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
425
426 /* Reset the start time; from now on, time is attributed to
427 TIMEVAR. */
428 start_time = now;
429
5e4adfba 430 fprintf (fp, _("\nExecution times (seconds)\n"));
2a9a326b
AS
431 for (id = 0; id < TIMEVAR_LAST; ++id)
432 {
433 struct timevar_def *tv = &timevars[id];
434
435 /* Don't print the total execution time here; that goes at the
436 end. */
437 if (id == TV_TOTAL)
438 continue;
439
26026d38
AS
440 /* Don't print timing variables that were never used. */
441 if (!tv->used)
442 continue;
443
2a9a326b
AS
444 /* The timing variable name. */
445 fprintf (fp, " %-22s:", tv->name);
446
447#ifdef HAVE_USER_TIME
448 /* Print user-mode time for this process. */
449 fprintf (fp, "%4ld.%02ld (%2.0f%%) usr",
450 tv->elapsed.user / 1000000,
451 (tv->elapsed.user % 1000000) / 10000,
452 (total->user == 0) ? 0.0
453 : (100.0 * tv->elapsed.user / (double) total->user));
454#endif /* HAVE_USER_TIME */
455
456#ifdef HAVE_SYS_TIME
457 /* Print system-mode time for this process. */
458 fprintf (fp, "%4ld.%02ld (%2.0f%%) sys",
459 tv->elapsed.sys / 1000000,
460 (tv->elapsed.sys % 1000000) / 10000,
461 (total->sys == 0) ? 0.0
462 : (100.0 * tv->elapsed.sys / (double) total->sys));
463#endif /* HAVE_SYS_TIME */
464
465#ifdef HAVE_WALL_TIME
466 /* Print wall clock time elapsed. */
467 fprintf (fp, "%4ld.%02ld (%2.0f%%) wall",
468 tv->elapsed.wall / 1000000,
469 (tv->elapsed.wall % 1000000) / 10000,
470 (total->wall == 0) ? 0.0
471 : (100.0 * tv->elapsed.wall / (double) total->wall));
472#endif /* HAVE_WALL_TIME */
473
474 fprintf (fp, "\n");
475 }
476
477 /* Print total time. */
5e4adfba 478 fprintf (fp, _(" TOTAL :"));
2a9a326b
AS
479#ifdef HAVE_USER_TIME
480 fprintf (fp, "%4ld.%02ld ",
481 total->user / 1000000, (total->user % 1000000) / 10000);
482#endif
483#ifdef HAVE_SYS_TIME
484 fprintf (fp, "%4ld.%02ld ",
485 total->sys / 1000000, (total->sys % 1000000) / 10000);
486#endif
487#ifdef HAVE_WALL_TIME
488 fprintf (fp, "%4ld.%02ld\n",
489 total->wall / 1000000, (total->wall % 1000000) / 10000);
490#endif
491
492#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
493 || defined (HAVE_WALL_TIME) */
494}
495
496/* Returns time (user + system) used so far by the compiler process,
497 in microseconds. */
498
499long
500get_run_time ()
501{
502 struct timevar_time_def total_elapsed;
503 timevar_get (TV_TOTAL, &total_elapsed);
504 return total_elapsed.user + total_elapsed.sys;
505}
506
507/* Prints a message to stderr stating that time elapsed in STR is
508 TOTAL (given in microseconds). */
509
510void
511print_time (str, total)
512 const char *str;
513 long total;
514{
515 long all_time = get_run_time ();
516 fprintf (stderr,
5e4adfba 517 _("time in %s: %ld.%06ld (%ld%%)\n"),
2a9a326b
AS
518 str, total / 1000000, total % 1000000,
519 all_time == 0 ? 0
520 : (long) (((100.0 * (double) total) / (double) all_time) + .5));
521}