timevar.c 13.7 KB
Newer Older
1
/* Timing variables for measuring compiler performance.
2
   Copyright (C) 2000, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
3 4
   Contributed by Alex Samuel <samuel@codesourcery.com>

5
This file is part of GCC.
6

7 8
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11

12 13 14 15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
16

17
You should have received a copy of the GNU General Public License
18 19
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
20 21 22 23 24 25

#include "config.h"
#include "system.h"
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
26 27 28
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
29 30 31 32 33 34
#include "coretypes.h"
#include "tm.h"
#include "intl.h"
#include "rtl.h"
#include "toplev.h"

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
#ifndef HAVE_CLOCK_T
typedef int clock_t;
#endif

#ifndef HAVE_STRUCT_TMS
struct tms
{
  clock_t tms_utime;
  clock_t tms_stime;
  clock_t tms_cutime;
  clock_t tms_cstime;
};
#endif

#ifndef RUSAGE_SELF
# define RUSAGE_SELF 0
#endif

/* Calculation of scale factor to convert ticks to microseconds.
   We mustn't use CLOCKS_PER_SEC except with clock().  */
#if HAVE_SYSCONF && defined _SC_CLK_TCK
# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
#else
# ifdef CLK_TCK
#  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
# else
#  ifdef HZ
#   define TICKS_PER_SECOND HZ  /* traditional UNIX */
#  else
#   define TICKS_PER_SECOND 100 /* often the correct value */
#  endif
# endif
#endif

/* Prefer times to getrusage to clock (each gives successively less
   information).  */
#ifdef HAVE_TIMES
72
# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
73
  extern clock_t times (struct tms *);
74
# endif
75 76 77 78 79 80
# define USE_TIMES
# define HAVE_USER_TIME
# define HAVE_SYS_TIME
# define HAVE_WALL_TIME
#else
#ifdef HAVE_GETRUSAGE
81
# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
82
  extern int getrusage (int, struct rusage *);
83
# endif
84 85 86 87 88
# define USE_GETRUSAGE
# define HAVE_USER_TIME
# define HAVE_SYS_TIME
#else
#ifdef HAVE_CLOCK
89
# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
90
  extern clock_t clock (void);
91
# endif
92 93 94 95 96
# define USE_CLOCK
# define HAVE_USER_TIME
#endif
#endif
#endif
97

98 99 100 101 102
/* libc is very likely to have snuck a call to sysconf() into one of
   the underlying constants, and that can be very slow, so we have to
   precompute them.  Whose wonderful idea was it to make all those
   _constants_ variable at run time, anyway?  */
#ifdef USE_TIMES
103 104
static double ticks_to_msec;
#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
105 106 107
#endif

#ifdef USE_CLOCK
108 109
static double clocks_to_msec;
#define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
110 111
#endif

112
#include "flags.h"
113 114
#include "timevar.h"

115
bool timevar_enable;
116

117 118 119 120 121 122 123 124 125
/* Total amount of memory allocated by garbage collector.  */

size_t timevar_ggc_mem_total;

/* The amount of memory that will cause us to report the timevar even
   if the time spent is not significant.  */

#define GGC_MEM_BOUND (1 << 20)

126
/* See timevar.h for an explanation of timing variables.  */
127

128 129 130 131 132 133 134 135 136 137 138
/* A timing variable.  */

struct timevar_def
{
  /* Elapsed time for this variable.  */
  struct timevar_time_def elapsed;

  /* If this variable is timed independently of the timing stack,
     using timevar_start, this contains the start time.  */
  struct timevar_time_def start_time;

139 140 141
  /* The name of this timing variable.  */
  const char *name;

142
  /* Nonzero if this timing variable is running as a standalone
143
     timer.  */
144
  unsigned standalone : 1;
145

146
  /* Nonzero if this timing variable was ever started or pushed onto
147 148
     the timing stack.  */
  unsigned used : 1;
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
};

/* An element on the timing stack.  Elapsed time is attributed to the
   topmost timing variable on the stack.  */

struct timevar_stack_def
{
  /* The timing variable at this stack level.  */
  struct timevar_def *timevar;

  /* The next lower timing variable context in the stack.  */
  struct timevar_stack_def *next;
};

/* Declared timing variables.  Constructed from the contents of
   timevar.def.  */
static struct timevar_def timevars[TIMEVAR_LAST];

/* The top of the timing stack.  */
static struct timevar_stack_def *stack;

170 171 172 173
/* A list of unused (i.e. allocated and subsequently popped)
   timevar_stack_def instances.  */
static struct timevar_stack_def *unused_stack_instances;

174 175 176 177 178
/* The time at which the topmost element on the timing stack was
   pushed.  Time elapsed since then is attributed to the topmost
   element.  */
static struct timevar_time_def start_time;

179 180 181 182
static void get_time (struct timevar_time_def *);
static void timevar_accumulate (struct timevar_time_def *,
				struct timevar_time_def *,
				struct timevar_time_def *);
183 184 185

/* Fill the current times into TIME.  The definition of this function
   also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
Mike Stump committed
186
   HAVE_WALL_TIME macros.  */
187 188

static void
189
get_time (struct timevar_time_def *now)
190
{
191 192 193
  now->user = 0;
  now->sys  = 0;
  now->wall = 0;
194
  now->ggc_mem = timevar_ggc_mem_total;
195

196
  if (!timevar_enable)
197
    return;
198 199

  {
200
#ifdef USE_TIMES
201
    struct tms tms;
202 203 204
    now->wall = times (&tms)  * ticks_to_msec;
    now->user = tms.tms_utime * ticks_to_msec;
    now->sys  = tms.tms_stime * ticks_to_msec;
205 206
#endif
#ifdef USE_GETRUSAGE
207
    struct rusage rusage;
208
    getrusage (RUSAGE_SELF, &rusage);
209 210
    now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
    now->sys  = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
211 212
#endif
#ifdef USE_CLOCK
213
    now->user = clock () * clocks_to_msec;
214
#endif
215
  }
216
}
217 218 219

/* Add the difference between STOP_TIME and START_TIME to TIMER.  */

Kazu Hirata committed
220
static void
221 222 223
timevar_accumulate (struct timevar_time_def *timer,
		    struct timevar_time_def *start_time,
		    struct timevar_time_def *stop_time)
224 225 226 227
{
  timer->user += stop_time->user - start_time->user;
  timer->sys += stop_time->sys - start_time->sys;
  timer->wall += stop_time->wall - start_time->wall;
228
  timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
229 230 231 232 233
}

/* Initialize timing variables.  */

void
234
timevar_init (void)
235
{
236
  timevar_enable = true;
237

238
  /* Zero all elapsed times.  */
239
  memset (timevars, 0, sizeof (timevars));
240 241

  /* Initialize the names of timing variables.  */
242 243
#define DEFTIMEVAR(identifier__, name__) \
  timevars[identifier__].name = name__;
244 245
#include "timevar.def"
#undef DEFTIMEVAR
246 247 248 249 250 251 252

#ifdef USE_TIMES
  ticks_to_msec = TICKS_TO_MSEC;
#endif
#ifdef USE_CLOCK
  clocks_to_msec = CLOCKS_TO_MSEC;
#endif
253 254 255 256 257
}

/* Push TIMEVAR onto the timing stack.  No further elapsed time is
   attributed to the previous topmost timing variable on the stack;
   subsequent elapsed time is attributed to TIMEVAR, until it is
Kazu Hirata committed
258
   popped or another element is pushed on top.
259 260 261 262

   TIMEVAR cannot be running as a standalone timer.  */

void
263
timevar_push_1 (timevar_id_t timevar)
264 265 266 267 268
{
  struct timevar_def *tv = &timevars[timevar];
  struct timevar_stack_def *context;
  struct timevar_time_def now;

269 270 271
  /* Mark this timing variable as used.  */
  tv->used = 1;

272
  /* Can't push a standalone timer.  */
273
  gcc_assert (!tv->standalone);
274 275 276 277 278 279 280 281 282 283

  /* What time is it?  */
  get_time (&now);

  /* If the stack isn't empty, attribute the current elapsed time to
     the old topmost element.  */
  if (stack)
    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);

  /* Reset the start time; from now on, time is attributed to
284
     TIMEVAR.  */
285 286
  start_time = now;

287 288
  /* See if we have a previously-allocated stack instance.  If so,
     take it off the list.  If not, malloc a new one.  */
Kazu Hirata committed
289
  if (unused_stack_instances != NULL)
290 291 292 293 294
    {
      context = unused_stack_instances;
      unused_stack_instances = unused_stack_instances->next;
    }
  else
295
    context = XNEW (struct timevar_stack_def);
296 297

  /* Fill it in and put it on the stack.  */
298 299 300 301 302 303 304 305 306 307 308 309
  context->timevar = tv;
  context->next = stack;
  stack = context;
}

/* Pop the topmost timing variable element off the timing stack.  The
   popped variable must be TIMEVAR.  Elapsed time since the that
   element was pushed on, or since it was last exposed on top of the
   stack when the element above it was popped off, is credited to that
   timing variable.  */

void
310
timevar_pop_1 (timevar_id_t timevar)
311 312
{
  struct timevar_time_def now;
313 314
  struct timevar_stack_def *popped = stack;

315 316
  gcc_assert (&timevars[timevar] == stack->timevar);
  
317 318 319 320
  /* What time is it?  */
  get_time (&now);

  /* Attribute the elapsed time to the element we're popping.  */
321
  timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
322 323 324 325 326

  /* Reset the start time; from now on, time is attributed to the
     element just exposed on the stack.  */
  start_time = now;

327 328 329 330 331 332 333
  /* Take the item off the stack.  */
  stack = stack->next;

  /* Don't delete the stack element; instead, add it to the list of
     unused elements for later use.  */
  popped->next = unused_stack_instances;
  unused_stack_instances = popped;
334 335 336 337 338 339 340
}

/* Start timing TIMEVAR independently of the timing stack.  Elapsed
   time until timevar_stop is called for the same timing variable is
   attributed to TIMEVAR.  */

void
341
timevar_start (timevar_id_t timevar)
342 343 344
{
  struct timevar_def *tv = &timevars[timevar];

345
  if (!timevar_enable)
346 347 348 349 350
    return;

  /* Mark this timing variable as used.  */
  tv->used = 1;

351 352
  /* Don't allow the same timing variable to be started more than
     once.  */
353
  gcc_assert (!tv->standalone);
354 355 356 357 358 359 360 361 362
  tv->standalone = 1;

  get_time (&tv->start_time);
}

/* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
   is attributed to it.  */

void
363
timevar_stop (timevar_id_t timevar)
364 365 366 367
{
  struct timevar_def *tv = &timevars[timevar];
  struct timevar_time_def now;

368
  if (!timevar_enable)
369 370
    return;

371
  /* TIMEVAR must have been started via timevar_start.  */
372
  gcc_assert (tv->standalone);
373 374 375 376 377 378 379 380 381 382

  get_time (&now);
  timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
}

/* Summarize timing variables to FP.  The timing variable TV_TOTAL has
   a special meaning -- it's considered to be the total elapsed time,
   for normalizing the others, and is displayed last.  */

void
383
timevar_print (FILE *fp)
384 385 386
{
  /* Only print stuff if we have some sort of time information.  */
#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
387
  unsigned int /* timevar_id_t */ id;
388
  struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
389
  struct timevar_time_def now;
390

391
  if (!timevar_enable)
392 393
    return;

394 395 396 397 398 399 400 401 402 403 404 405 406 407
  /* Update timing information in case we're calling this from GDB.  */

  if (fp == 0)
    fp = stderr;

  /* What time is it?  */
  get_time (&now);

  /* If the stack isn't empty, attribute the current elapsed time to
     the old topmost element.  */
  if (stack)
    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);

  /* Reset the start time; from now on, time is attributed to
408
     TIMEVAR.  */
409 410
  start_time = now;

411
  fputs (_("\nExecution times (seconds)\n"), fp);
412
  for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
413
    {
414
      struct timevar_def *tv = &timevars[(timevar_id_t) id];
415
      const double tiny = 5e-3;
416 417 418

      /* Don't print the total execution time here; that goes at the
	 end.  */
419
      if ((timevar_id_t) id == TV_TOTAL)
420 421
	continue;

422 423 424 425
      /* Don't print timing variables that were never used.  */
      if (!tv->used)
	continue;

426 427
      /* Don't print timing variables if we're going to get a row of
         zeroes.  */
428 429
      if (tv->elapsed.user < tiny
	  && tv->elapsed.sys < tiny
430 431
	  && tv->elapsed.wall < tiny
	  && tv->elapsed.ggc_mem < GGC_MEM_BOUND)
432 433
	continue;

434 435 436 437 438
      /* The timing variable name.  */
      fprintf (fp, " %-22s:", tv->name);

#ifdef HAVE_USER_TIME
      /* Print user-mode time for this process.  */
Kazu Hirata committed
439
      fprintf (fp, "%7.2f (%2.0f%%) usr",
440 441
	       tv->elapsed.user,
	       (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
442 443 444 445
#endif /* HAVE_USER_TIME */

#ifdef HAVE_SYS_TIME
      /* Print system-mode time for this process.  */
Kazu Hirata committed
446
      fprintf (fp, "%7.2f (%2.0f%%) sys",
447 448
	       tv->elapsed.sys,
	       (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
449 450 451 452
#endif /* HAVE_SYS_TIME */

#ifdef HAVE_WALL_TIME
      /* Print wall clock time elapsed.  */
Kazu Hirata committed
453
      fprintf (fp, "%7.2f (%2.0f%%) wall",
454 455
	       tv->elapsed.wall,
	       (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
456 457
#endif /* HAVE_WALL_TIME */

458 459 460 461 462 463 464
      /* Print the amount of ggc memory allocated.  */
      fprintf (fp, "%8u kB (%2.0f%%) ggc",
	       (unsigned) (tv->elapsed.ggc_mem >> 10),
	       (total->ggc_mem == 0
		? 0
		: (float) tv->elapsed.ggc_mem / total->ggc_mem) * 100);

465
      putc ('\n', fp);
466 467 468
    }

  /* Print total time.  */
469
  fputs (_(" TOTAL                 :"), fp);
470
#ifdef HAVE_USER_TIME
471
  fprintf (fp, "%7.2f          ", total->user);
Kazu Hirata committed
472
#endif
473
#ifdef HAVE_SYS_TIME
474
  fprintf (fp, "%7.2f          ", total->sys);
475 476
#endif
#ifdef HAVE_WALL_TIME
477
  fprintf (fp, "%7.2f           ", total->wall);
478
#endif
479
  fprintf (fp, "%8u kB\n", (unsigned) (total->ggc_mem >> 10));
Kazu Hirata committed
480

481 482
#ifdef ENABLE_CHECKING
  fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
483 484
  fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
#endif
485 486 487
#ifndef ENABLE_ASSERT_CHECKING
  fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
  fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
488 489
#endif

Kazu Hirata committed
490
#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
491 492 493 494 495 496 497
	  || defined (HAVE_WALL_TIME) */
}

/* Prints a message to stderr stating that time elapsed in STR is
   TOTAL (given in microseconds).  */

void
498
print_time (const char *str, long total)
499 500 501
{
  long all_time = get_run_time ();
  fprintf (stderr,
502
	   _("time in %s: %ld.%06ld (%ld%%)\n"),
503
	   str, total / 1000000, total % 1000000,
Kazu Hirata committed
504 505
	   all_time == 0 ? 0
	   : (long) (((100.0 * (double) total) / (double) all_time) + .5));
506
}