timevar.c revision 132718
1250003Sadrian/* Timing variables for measuring compiler performance.
2250003Sadrian   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
3250003Sadrian   Contributed by Alex Samuel <samuel@codesourcery.com>
4250003Sadrian
5250003SadrianThis file is part of GCC.
6250003Sadrian
7250003SadrianGCC is free software; you can redistribute it and/or modify it under
8250003Sadrianthe terms of the GNU General Public License as published by the Free
9250003SadrianSoftware Foundation; either version 2, or (at your option) any later
10250003Sadrianversion.
11250003Sadrian
12250003SadrianGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13250003SadrianWARRANTY; without even the implied warranty of MERCHANTABILITY or
14250003SadrianFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15250003Sadrianfor more details.
16250003Sadrian
17250003SadrianYou should have received a copy of the GNU General Public License
18250003Sadrianalong with GCC; see the file COPYING.  If not, write to the Free
19250003SadrianSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
20250003Sadrian02111-1307, USA.  */
21250003Sadrian
22250003Sadrian#include "config.h"
23250003Sadrian#include "system.h"
24250003Sadrian#ifdef HAVE_SYS_TIMES_H
25250003Sadrian# include <sys/times.h>
26250003Sadrian#endif
27250003Sadrian#ifdef HAVE_SYS_RESOURCE_H
28250003Sadrian#include <sys/resource.h>
29250003Sadrian#endif
30250003Sadrian#include "coretypes.h"
31250003Sadrian#include "tm.h"
32250003Sadrian#include "intl.h"
33250003Sadrian#include "rtl.h"
34250003Sadrian#include "toplev.h"
35250003Sadrian
36250003Sadrian#ifndef HAVE_CLOCK_T
37250003Sadriantypedef int clock_t;
38250003Sadrian#endif
39250003Sadrian
40250003Sadrian#ifndef HAVE_STRUCT_TMS
41250003Sadrianstruct tms
42250003Sadrian{
43250003Sadrian  clock_t tms_utime;
44250003Sadrian  clock_t tms_stime;
45250003Sadrian  clock_t tms_cutime;
46250003Sadrian  clock_t tms_cstime;
47250003Sadrian};
48250003Sadrian#endif
49250003Sadrian
50250003Sadrian#ifndef RUSAGE_SELF
51250003Sadrian# define RUSAGE_SELF 0
52250003Sadrian#endif
53250003Sadrian
54250003Sadrian/* Calculation of scale factor to convert ticks to microseconds.
55250003Sadrian   We mustn't use CLOCKS_PER_SEC except with clock().  */
56250003Sadrian#if HAVE_SYSCONF && defined _SC_CLK_TCK
57250003Sadrian# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
58250003Sadrian#else
59250003Sadrian# ifdef CLK_TCK
60250003Sadrian#  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
61250003Sadrian# else
62250003Sadrian#  ifdef HZ
63250003Sadrian#   define TICKS_PER_SECOND HZ  /* traditional UNIX */
64250003Sadrian#  else
65250003Sadrian#   define TICKS_PER_SECOND 100 /* often the correct value */
66250003Sadrian#  endif
67250003Sadrian# endif
68250003Sadrian#endif
69250003Sadrian
70250003Sadrian/* Prefer times to getrusage to clock (each gives successively less
71250003Sadrian   information).  */
72250003Sadrian#ifdef HAVE_TIMES
73250003Sadrian# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
74250003Sadrian  extern clock_t times (struct tms *);
75250003Sadrian# endif
76250003Sadrian# define USE_TIMES
77250003Sadrian# define HAVE_USER_TIME
78250003Sadrian# define HAVE_SYS_TIME
79250003Sadrian# define HAVE_WALL_TIME
80250003Sadrian#else
81250003Sadrian#ifdef HAVE_GETRUSAGE
82250003Sadrian# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
83250003Sadrian  extern int getrusage (int, struct rusage *);
84250003Sadrian# endif
85250003Sadrian# define USE_GETRUSAGE
86250003Sadrian# define HAVE_USER_TIME
87250003Sadrian# define HAVE_SYS_TIME
88250003Sadrian#else
89250003Sadrian#ifdef HAVE_CLOCK
90250003Sadrian# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
91250003Sadrian  extern clock_t clock (void);
92250003Sadrian# endif
93250003Sadrian# define USE_CLOCK
94250003Sadrian# define HAVE_USER_TIME
95250003Sadrian#endif
96250003Sadrian#endif
97250003Sadrian#endif
98250003Sadrian
99250003Sadrian/* libc is very likely to have snuck a call to sysconf() into one of
100250003Sadrian   the underlying constants, and that can be very slow, so we have to
101250003Sadrian   precompute them.  Whose wonderful idea was it to make all those
102250003Sadrian   _constants_ variable at run time, anyway?  */
103250003Sadrian#ifdef USE_TIMES
104250003Sadrianstatic double ticks_to_msec;
105250003Sadrian#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
106250003Sadrian#endif
107250003Sadrian
108250003Sadrian#ifdef USE_CLOCK
109250003Sadrianstatic double clocks_to_msec;
110250003Sadrian#define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
111250003Sadrian#endif
112250003Sadrian
113250003Sadrian#include "flags.h"
114250003Sadrian#include "timevar.h"
115250003Sadrian
116250003Sadrianstatic bool timevar_enable;
117250003Sadrian
118250003Sadrian/* See timevar.h for an explanation of timing variables.  */
119250003Sadrian
120250003Sadrian/* A timing variable.  */
121250003Sadrian
122250003Sadrianstruct timevar_def
123250003Sadrian{
124250003Sadrian  /* Elapsed time for this variable.  */
125250003Sadrian  struct timevar_time_def elapsed;
126250003Sadrian
127250003Sadrian  /* If this variable is timed independently of the timing stack,
128250003Sadrian     using timevar_start, this contains the start time.  */
129250003Sadrian  struct timevar_time_def start_time;
130250003Sadrian
131250003Sadrian  /* The name of this timing variable.  */
132250003Sadrian  const char *name;
133250003Sadrian
134250003Sadrian  /* Nonzero if this timing variable is running as a standalone
135250003Sadrian     timer.  */
136250003Sadrian  unsigned standalone : 1;
137250003Sadrian
138250003Sadrian  /* Nonzero if this timing variable was ever started or pushed onto
139250003Sadrian     the timing stack.  */
140250003Sadrian  unsigned used : 1;
141250003Sadrian};
142250003Sadrian
143250003Sadrian/* An element on the timing stack.  Elapsed time is attributed to the
144250003Sadrian   topmost timing variable on the stack.  */
145250003Sadrian
146250003Sadrianstruct timevar_stack_def
147250003Sadrian{
148250003Sadrian  /* The timing variable at this stack level.  */
149250003Sadrian  struct timevar_def *timevar;
150250003Sadrian
151250003Sadrian  /* The next lower timing variable context in the stack.  */
152250003Sadrian  struct timevar_stack_def *next;
153250003Sadrian};
154250003Sadrian
155250003Sadrian/* Declared timing variables.  Constructed from the contents of
156250003Sadrian   timevar.def.  */
157250003Sadrianstatic struct timevar_def timevars[TIMEVAR_LAST];
158250003Sadrian
159250003Sadrian/* The top of the timing stack.  */
160250003Sadrianstatic struct timevar_stack_def *stack;
161250003Sadrian
162250003Sadrian/* A list of unused (i.e. allocated and subsequently popped)
163250003Sadrian   timevar_stack_def instances.  */
164250003Sadrianstatic struct timevar_stack_def *unused_stack_instances;
165250003Sadrian
166250003Sadrian/* The time at which the topmost element on the timing stack was
167250003Sadrian   pushed.  Time elapsed since then is attributed to the topmost
168250003Sadrian   element.  */
169250003Sadrianstatic struct timevar_time_def start_time;
170250003Sadrian
171250003Sadrianstatic void get_time (struct timevar_time_def *);
172250003Sadrianstatic void timevar_accumulate (struct timevar_time_def *,
173250003Sadrian				struct timevar_time_def *,
174250003Sadrian				struct timevar_time_def *);
175250003Sadrian
176250003Sadrian/* Fill the current times into TIME.  The definition of this function
177250003Sadrian   also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
178250003Sadrian   HAVE_WALL_TIME macros.  */
179250003Sadrian
180250003Sadrianstatic void
181250003Sadrianget_time (struct timevar_time_def *now)
182250003Sadrian{
183250003Sadrian  now->user = 0;
184250003Sadrian  now->sys  = 0;
185250003Sadrian  now->wall = 0;
186250003Sadrian
187250003Sadrian  if (!timevar_enable)
188250003Sadrian    return;
189250003Sadrian
190250003Sadrian  {
191250003Sadrian#ifdef USE_TIMES
192250003Sadrian    struct tms tms;
193250003Sadrian    now->wall = times (&tms)  * ticks_to_msec;
194250003Sadrian    now->user = tms.tms_utime * ticks_to_msec;
195250003Sadrian    now->sys  = tms.tms_stime * ticks_to_msec;
196250003Sadrian#endif
197250003Sadrian#ifdef USE_GETRUSAGE
198250003Sadrian    struct rusage rusage;
199250003Sadrian    getrusage (RUSAGE_SELF, &rusage);
200250003Sadrian    now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
201250003Sadrian    now->sys  = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
202250003Sadrian#endif
203250003Sadrian#ifdef USE_CLOCK
204250003Sadrian    now->user = clock () * clocks_to_msec;
205250003Sadrian#endif
206250003Sadrian  }
207250003Sadrian}
208250003Sadrian
209250003Sadrian/* Add the difference between STOP_TIME and START_TIME to TIMER.  */
210250003Sadrian
211250003Sadrianstatic void
212250003Sadriantimevar_accumulate (struct timevar_time_def *timer,
213250003Sadrian		    struct timevar_time_def *start_time,
214250003Sadrian		    struct timevar_time_def *stop_time)
215250003Sadrian{
216250003Sadrian  timer->user += stop_time->user - start_time->user;
217250003Sadrian  timer->sys += stop_time->sys - start_time->sys;
218250003Sadrian  timer->wall += stop_time->wall - start_time->wall;
219250003Sadrian}
220250003Sadrian
221250003Sadrian/* Initialize timing variables.  */
222250003Sadrian
223250003Sadrianvoid
224250003Sadriantimevar_init (void)
225250003Sadrian{
226250003Sadrian  timevar_enable = true;
227250003Sadrian
228250003Sadrian  /* Zero all elapsed times.  */
229250003Sadrian  memset (timevars, 0, sizeof (timevars));
230250003Sadrian
231250003Sadrian  /* Initialize the names of timing variables.  */
232250003Sadrian#define DEFTIMEVAR(identifier__, name__) \
233250003Sadrian  timevars[identifier__].name = name__;
234250003Sadrian#include "timevar.def"
235250003Sadrian#undef DEFTIMEVAR
236250003Sadrian
237250003Sadrian#ifdef USE_TIMES
238250003Sadrian  ticks_to_msec = TICKS_TO_MSEC;
239250003Sadrian#endif
240250003Sadrian#ifdef USE_CLOCK
241250003Sadrian  clocks_to_msec = CLOCKS_TO_MSEC;
242250003Sadrian#endif
243250003Sadrian}
244250003Sadrian
245250003Sadrian/* Push TIMEVAR onto the timing stack.  No further elapsed time is
246250003Sadrian   attributed to the previous topmost timing variable on the stack;
247250003Sadrian   subsequent elapsed time is attributed to TIMEVAR, until it is
248250003Sadrian   popped or another element is pushed on top.
249250003Sadrian
250250003Sadrian   TIMEVAR cannot be running as a standalone timer.  */
251250003Sadrian
252250003Sadrianvoid
253250003Sadriantimevar_push (timevar_id_t timevar)
254250003Sadrian{
255250003Sadrian  struct timevar_def *tv = &timevars[timevar];
256250003Sadrian  struct timevar_stack_def *context;
257250003Sadrian  struct timevar_time_def now;
258250003Sadrian
259250003Sadrian  if (!timevar_enable)
260250003Sadrian    return;
261250003Sadrian
262250003Sadrian  /* Mark this timing variable as used.  */
263250003Sadrian  tv->used = 1;
264250003Sadrian
265250003Sadrian  /* Can't push a standalone timer.  */
266250003Sadrian  if (tv->standalone)
267250003Sadrian    abort ();
268250003Sadrian
269250003Sadrian  /* What time is it?  */
270250003Sadrian  get_time (&now);
271250003Sadrian
272250003Sadrian  /* If the stack isn't empty, attribute the current elapsed time to
273250003Sadrian     the old topmost element.  */
274250003Sadrian  if (stack)
275250003Sadrian    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
276250003Sadrian
277250003Sadrian  /* Reset the start time; from now on, time is attributed to
278250003Sadrian     TIMEVAR.  */
279250003Sadrian  start_time = now;
280250003Sadrian
281250003Sadrian  /* See if we have a previously-allocated stack instance.  If so,
282250003Sadrian     take it off the list.  If not, malloc a new one.  */
283250003Sadrian  if (unused_stack_instances != NULL)
284250003Sadrian    {
285250003Sadrian      context = unused_stack_instances;
286250003Sadrian      unused_stack_instances = unused_stack_instances->next;
287250003Sadrian    }
288250003Sadrian  else
289250003Sadrian    context = xmalloc (sizeof (struct timevar_stack_def));
290250003Sadrian
291250003Sadrian  /* Fill it in and put it on the stack.  */
292250003Sadrian  context->timevar = tv;
293250003Sadrian  context->next = stack;
294250003Sadrian  stack = context;
295250003Sadrian}
296250003Sadrian
297250003Sadrian/* Pop the topmost timing variable element off the timing stack.  The
298250003Sadrian   popped variable must be TIMEVAR.  Elapsed time since the that
299250003Sadrian   element was pushed on, or since it was last exposed on top of the
300250003Sadrian   stack when the element above it was popped off, is credited to that
301250003Sadrian   timing variable.  */
302250003Sadrian
303250003Sadrianvoid
304250003Sadriantimevar_pop (timevar_id_t timevar)
305250003Sadrian{
306250003Sadrian  struct timevar_time_def now;
307250003Sadrian  struct timevar_stack_def *popped = stack;
308250003Sadrian
309250003Sadrian  if (!timevar_enable)
310250003Sadrian    return;
311250003Sadrian
312250003Sadrian  if (&timevars[timevar] != stack->timevar)
313250003Sadrian    {
314250003Sadrian      sorry ("cannot timevar_pop '%s' when top of timevars stack is '%s'",
315250003Sadrian             timevars[timevar].name, stack->timevar->name);
316250003Sadrian      abort ();
317250003Sadrian    }
318250003Sadrian
319250003Sadrian  /* What time is it?  */
320250003Sadrian  get_time (&now);
321250003Sadrian
322250003Sadrian  /* Attribute the elapsed time to the element we're popping.  */
323250003Sadrian  timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
324250003Sadrian
325250003Sadrian  /* Reset the start time; from now on, time is attributed to the
326250003Sadrian     element just exposed on the stack.  */
327250003Sadrian  start_time = now;
328250003Sadrian
329250003Sadrian  /* Take the item off the stack.  */
330250003Sadrian  stack = stack->next;
331250003Sadrian
332250003Sadrian  /* Don't delete the stack element; instead, add it to the list of
333250003Sadrian     unused elements for later use.  */
334250003Sadrian  popped->next = unused_stack_instances;
335250003Sadrian  unused_stack_instances = popped;
336250003Sadrian}
337250003Sadrian
338250003Sadrian/* Start timing TIMEVAR independently of the timing stack.  Elapsed
339250003Sadrian   time until timevar_stop is called for the same timing variable is
340250003Sadrian   attributed to TIMEVAR.  */
341250003Sadrian
342250003Sadrianvoid
343250003Sadriantimevar_start (timevar_id_t timevar)
344250003Sadrian{
345250003Sadrian  struct timevar_def *tv = &timevars[timevar];
346250003Sadrian
347250003Sadrian  if (!timevar_enable)
348250003Sadrian    return;
349250003Sadrian
350250003Sadrian  /* Mark this timing variable as used.  */
351250003Sadrian  tv->used = 1;
352250003Sadrian
353250003Sadrian  /* Don't allow the same timing variable to be started more than
354250003Sadrian     once.  */
355250003Sadrian  if (tv->standalone)
356250003Sadrian    abort ();
357250003Sadrian  tv->standalone = 1;
358250003Sadrian
359250003Sadrian  get_time (&tv->start_time);
360250003Sadrian}
361250003Sadrian
362250003Sadrian/* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
363250003Sadrian   is attributed to it.  */
364250003Sadrian
365250003Sadrianvoid
366250003Sadriantimevar_stop (timevar_id_t timevar)
367250003Sadrian{
368250003Sadrian  struct timevar_def *tv = &timevars[timevar];
369250003Sadrian  struct timevar_time_def now;
370250003Sadrian
371250003Sadrian  if (!timevar_enable)
372250003Sadrian    return;
373250003Sadrian
374250003Sadrian  /* TIMEVAR must have been started via timevar_start.  */
375250003Sadrian  if (!tv->standalone)
376250003Sadrian    abort ();
377250003Sadrian
378250003Sadrian  get_time (&now);
379250003Sadrian  timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
380250003Sadrian}
381250003Sadrian
382250003Sadrian/* Fill the elapsed time for TIMEVAR into ELAPSED.  Returns
383250003Sadrian   update-to-date information even if TIMEVAR is currently running.  */
384250003Sadrian
385250003Sadrianvoid
386250003Sadriantimevar_get (timevar_id_t timevar, struct timevar_time_def *elapsed)
387250003Sadrian{
388250003Sadrian  struct timevar_def *tv = &timevars[timevar];
389250003Sadrian  struct timevar_time_def now;
390250003Sadrian
391250003Sadrian  *elapsed = tv->elapsed;
392250003Sadrian
393250003Sadrian  /* Is TIMEVAR currently running as a standalone timer?  */
394250003Sadrian  if (tv->standalone)
395250003Sadrian    {
396250003Sadrian      get_time (&now);
397250003Sadrian      timevar_accumulate (elapsed, &tv->start_time, &now);
398250003Sadrian    }
399250003Sadrian  /* Or is TIMEVAR at the top of the timer stack?  */
400250003Sadrian  else if (stack->timevar == tv)
401250003Sadrian    {
402250003Sadrian      get_time (&now);
403250003Sadrian      timevar_accumulate (elapsed, &start_time, &now);
404250003Sadrian    }
405250003Sadrian}
406250003Sadrian
407250003Sadrian/* Summarize timing variables to FP.  The timing variable TV_TOTAL has
408250003Sadrian   a special meaning -- it's considered to be the total elapsed time,
409250003Sadrian   for normalizing the others, and is displayed last.  */
410250003Sadrian
411250003Sadrianvoid
412250003Sadriantimevar_print (FILE *fp)
413250003Sadrian{
414250003Sadrian  /* Only print stuff if we have some sort of time information.  */
415250003Sadrian#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
416250003Sadrian  unsigned int /* timevar_id_t */ id;
417250003Sadrian  struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
418250003Sadrian  struct timevar_time_def now;
419250003Sadrian
420250003Sadrian  if (!timevar_enable)
421250003Sadrian    return;
422250003Sadrian
423250003Sadrian  /* Update timing information in case we're calling this from GDB.  */
424250003Sadrian
425250003Sadrian  if (fp == 0)
426250003Sadrian    fp = stderr;
427250003Sadrian
428250003Sadrian  /* What time is it?  */
429250003Sadrian  get_time (&now);
430250003Sadrian
431250003Sadrian  /* If the stack isn't empty, attribute the current elapsed time to
432250003Sadrian     the old topmost element.  */
433250003Sadrian  if (stack)
434250003Sadrian    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
435250003Sadrian
436250003Sadrian  /* Reset the start time; from now on, time is attributed to
437250003Sadrian     TIMEVAR.  */
438250003Sadrian  start_time = now;
439250003Sadrian
440250003Sadrian  fputs (_("\nExecution times (seconds)\n"), fp);
441250003Sadrian  for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
442250003Sadrian    {
443250003Sadrian      struct timevar_def *tv = &timevars[(timevar_id_t) id];
444250003Sadrian      const double tiny = 5e-3;
445250003Sadrian
446250003Sadrian      /* Don't print the total execution time here; that goes at the
447250003Sadrian	 end.  */
448250003Sadrian      if ((timevar_id_t) id == TV_TOTAL)
449250003Sadrian	continue;
450250003Sadrian
451250003Sadrian      /* Don't print timing variables that were never used.  */
452250003Sadrian      if (!tv->used)
453250003Sadrian	continue;
454250003Sadrian
455250003Sadrian      /* Don't print timing variables if we're going to get a row of
456250003Sadrian         zeroes.  */
457250003Sadrian      if (tv->elapsed.user < tiny
458250003Sadrian	  && tv->elapsed.sys < tiny
459250003Sadrian	  && tv->elapsed.wall < tiny)
460250003Sadrian	continue;
461250003Sadrian
462250003Sadrian      /* The timing variable name.  */
463250003Sadrian      fprintf (fp, " %-22s:", tv->name);
464250003Sadrian
465250003Sadrian#ifdef HAVE_USER_TIME
466250003Sadrian      /* Print user-mode time for this process.  */
467250003Sadrian      fprintf (fp, "%7.2f (%2.0f%%) usr",
468250003Sadrian	       tv->elapsed.user,
469250003Sadrian	       (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
470250003Sadrian#endif /* HAVE_USER_TIME */
471250003Sadrian
472250003Sadrian#ifdef HAVE_SYS_TIME
473250003Sadrian      /* Print system-mode time for this process.  */
474250003Sadrian      fprintf (fp, "%7.2f (%2.0f%%) sys",
475250003Sadrian	       tv->elapsed.sys,
476250003Sadrian	       (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
477250003Sadrian#endif /* HAVE_SYS_TIME */
478250003Sadrian
479250003Sadrian#ifdef HAVE_WALL_TIME
480250003Sadrian      /* Print wall clock time elapsed.  */
481250003Sadrian      fprintf (fp, "%7.2f (%2.0f%%) wall",
482250003Sadrian	       tv->elapsed.wall,
483250003Sadrian	       (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
484250003Sadrian#endif /* HAVE_WALL_TIME */
485250003Sadrian
486250003Sadrian      putc ('\n', fp);
487250003Sadrian    }
488250003Sadrian
489250003Sadrian  /* Print total time.  */
490250003Sadrian  fputs (_(" TOTAL                 :"), fp);
491250003Sadrian#ifdef HAVE_USER_TIME
492250003Sadrian  fprintf (fp, "%7.2f          ", total->user);
493250003Sadrian#endif
494250003Sadrian#ifdef HAVE_SYS_TIME
495250003Sadrian  fprintf (fp, "%7.2f          ", total->sys);
496250003Sadrian#endif
497250003Sadrian#ifdef HAVE_WALL_TIME
498250003Sadrian  fprintf (fp, "%7.2f\n", total->wall);
499250003Sadrian#endif
500250003Sadrian
501250003Sadrian#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
502250003Sadrian	  || defined (HAVE_WALL_TIME) */
503250003Sadrian}
504250003Sadrian
505250003Sadrian/* Prints a message to stderr stating that time elapsed in STR is
506250003Sadrian   TOTAL (given in microseconds).  */
507250003Sadrian
508250003Sadrianvoid
509250003Sadrianprint_time (const char *str, long total)
510250003Sadrian{
511250003Sadrian  long all_time = get_run_time ();
512250003Sadrian  fprintf (stderr,
513250003Sadrian	   _("time in %s: %ld.%06ld (%ld%%)\n"),
514250003Sadrian	   str, total / 1000000, total % 1000000,
515250003Sadrian	   all_time == 0 ? 0
516250003Sadrian	   : (long) (((100.0 * (double) total) / (double) all_time) + .5));
517250003Sadrian}
518250003Sadrian