OSDN Git Service

44ea96f35aba5fb3de7117cb1d9fd5a401620356
[pf3gnuchains/gcc-fork.git] / gcc / timevar.c
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
29 #include "flags.h"
30 #include "timevar.h"
31
32 /* See timevar.h for an explanation of timing variables.  */
33
34 /* This macro evaluates to non-zero if timing variables are enabled. */
35 #define TIMEVAR_ENABLE (!quiet_flag)
36
37 /* A timing variable.  */
38
39 struct 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
48   /* The name of this timing variable.  */
49   const char *name;
50
51   /* Non-zero if this timing variable is running as a standalone
52      timer.  */
53   unsigned standalone : 1;
54
55   /* Non-zero if this timing variable was ever started or pushed onto
56      the timing stack.  */
57   unsigned used : 1;
58 };
59
60 /* An element on the timing stack.  Elapsed time is attributed to the
61    topmost timing variable on the stack.  */
62
63 struct 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.  */
74 static struct timevar_def timevars[TIMEVAR_LAST];
75
76 /* The top of the timing stack.  */
77 static struct timevar_stack_def *stack;
78
79 /* A list of unused (i.e. allocated and subsequently popped)
80    timevar_stack_def instances.  */
81 static struct timevar_stack_def *unused_stack_instances;
82
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.  */
86 static struct timevar_time_def start_time;
87
88 static void get_time
89   PARAMS ((struct timevar_time_def *));
90 static void timevar_add
91   PARAMS ((struct timevar_time_def *, struct timevar_time_def *));
92 static 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
100 static void
101 get_time (now)
102      struct timevar_time_def *now;
103 {
104   now->user = 0;
105   now->sys  = 0;
106   now->wall = 0;
107
108   if (!TIMEVAR_ENABLE)
109     return;
110
111 #ifdef __BEOS__
112   /* Nothing.  */
113 #else /* not BeOS */
114 #if defined (_WIN32) && !defined (__CYGWIN__)
115   if (clock () >= 0)
116     now->user = clock () * 1000;
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);
126     now->wall = times (&tms) * tick;
127     now->user = tms.tms_utime * tick;
128     now->sys = tms.tms_stime * tick;
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
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);
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);
160     now->user 
161       = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
162     now->sys 
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;
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;
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
194 static void
195 timevar_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
206 static void 
207 timevar_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
219 void
220 init_timevar ()
221 {
222   if (!TIMEVAR_ENABLE)
223     return;
224
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
242 void
243 timevar_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
250   if (!TIMEVAR_ENABLE)
251     return;
252
253   /* Mark this timing variable as used.  */
254   tv->used = 1;
255
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
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.  */
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
295 void
296 timevar_pop (timevar)
297      timevar_id_t timevar;
298 {
299   struct timevar_time_def now;
300   struct timevar_stack_def *popped = stack;
301
302   if (!TIMEVAR_ENABLE)
303     return;
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.  */
312   timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
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
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;
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
331 void
332 timevar_start (timevar)
333      timevar_id_t timevar;
334 {
335   struct timevar_def *tv = &timevars[timevar];
336
337   if (!TIMEVAR_ENABLE)
338     return;
339
340   /* Mark this timing variable as used.  */
341   tv->used = 1;
342
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
355 void
356 timevar_stop (timevar)
357      timevar_id_t timevar;
358 {
359   struct timevar_def *tv = &timevars[timevar];
360   struct timevar_time_def now;
361
362   if (!TIMEVAR_ENABLE)
363     return;
364
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
376 void
377 timevar_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
400 void
401 timevar_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;
408   struct timevar_time_def now;
409
410   if (!TIMEVAR_ENABLE)
411     return;
412
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
430   fprintf (fp, "\nExecution times (seconds)\n");
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
440       /* Don't print timing variables that were never used.  */
441       if (!tv->used)
442         continue;
443
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.  */
478   fprintf (fp, " TOTAL                 :");
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
499 long
500 get_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
510 void
511 print_time (str, total)
512      const char *str;
513      long total;
514 {
515   long all_time = get_run_time ();
516   fprintf (stderr,
517            "time in %s: %ld.%06ld (%ld%%)\n",
518            str, total / 1000000, total % 1000000,
519            all_time == 0 ? 0
520            : (long) (((100.0 * (double) total) / (double) all_time) + .5));
521 }