# include <sys/times.h>
#endif
+#include "flags.h"
#include "timevar.h"
/* See timevar.h for an explanation of timing variables. */
+/* This macro evaluates to non-zero if timing variables are enabled. */
+#define TIMEVAR_ENABLE (!quiet_flag)
+
/* A timing variable. */
struct timevar_def
using timevar_start, this contains the start time. */
struct timevar_time_def start_time;
+ /* The name of this timing variable. */
+ const char *name;
+
/* Non-zero if this timing variable is running as a standalone
timer. */
- int standalone;
+ unsigned standalone : 1;
- /* The name of this timing variable. */
- const char *name;
+ /* Non-zero if this timing variable was ever started or pushed onto
+ the timing stack. */
+ unsigned used : 1;
};
/* An element on the timing stack. Elapsed time is attributed to the
/* The top of the timing stack. */
static struct timevar_stack_def *stack;
+/* A list of unused (i.e. allocated and subsequently popped)
+ timevar_stack_def instances. */
+static struct timevar_stack_def *unused_stack_instances;
+
/* The time at which the topmost element on the timing stack was
pushed. Time elapsed since then is attributed to the topmost
element. */
HAVA_WALL_TIME macros. */
static void
-get_time (time)
- struct timevar_time_def *time;
+get_time (now)
+ struct timevar_time_def *now;
{
- time->user = 0;
- time->sys = 0;
- time->wall = 0;
+ now->user = 0;
+ now->sys = 0;
+ now->wall = 0;
+
+ if (!TIMEVAR_ENABLE)
+ return;
#ifdef __BEOS__
/* Nothing. */
#else /* not BeOS */
#if defined (_WIN32) && !defined (__CYGWIN__)
if (clock () >= 0)
- time->user = clock () * 1000;
+ now->user = clock () * 1000;
#define HAVE_USER_TIME
#else /* not _WIN32 */
struct tms tms;
if (tick == 0)
tick = 1000000 / sysconf (_SC_CLK_TCK);
- time->wall = times (&tms) * tick;
- time->user = tms.tms_utime * tick;
- time->sys = tms.tms_stime * tick;
+ now->wall = times (&tms) * tick;
+ now->user = tms.tms_utime * tick;
+ now->sys = tms.tms_stime * tick;
}
#define HAVE_USER_TIME
#define HAVE_SYS_TIME
# define TICKS_PER_SECOND HZ /* traditional UNIX */
# endif
# endif
- time->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
- time->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
- time->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
+ now->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
+ now->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
+ now->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
}
#define HAVE_USER_TIME
#define HAVE_SYS_TIME
{
struct rusage rusage;
getrusage (0, &rusage);
- time->user
+ now->user
= rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
- time->sys
+ now->sys
= rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
}
#define HAVE_USER_TIME
int child_user_time;
int child_system_time;
} vms_times;
- time->wall = times ((void *) &vms_times) * 10000;
- time->user = vms_times.proc_user_time * 10000;
- time->sys = vms_times.proc_system_time * 10000;
+ now->wall = times ((void *) &vms_times) * 10000;
+ now->user = vms_times.proc_user_time * 10000;
+ now->sys = vms_times.proc_system_time * 10000;
}
#define HAVE_USER_TIME
#define HAVE_SYS_TIME
/* Initialize timing variables. */
void
-init_timevar (void)
+init_timevar ()
{
+ if (!TIMEVAR_ENABLE)
+ return;
+
/* Zero all elapsed times. */
memset ((void *) timevars, 0, sizeof (timevars));
struct timevar_stack_def *context;
struct timevar_time_def now;
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
/* Can't push a standalone timer. */
if (tv->standalone)
abort ();
TIMEVAR. */
start_time = now;
- /* Create a new stack element, and push it. */
- context = (struct timevar_stack_def *)
- xmalloc (sizeof (struct timevar_stack_def));
+ /* See if we have a previously-allocated stack instance. If so,
+ take it off the list. If not, malloc a new one. */
+ if (unused_stack_instances != NULL)
+ {
+ context = unused_stack_instances;
+ unused_stack_instances = unused_stack_instances->next;
+ }
+ else
+ context = (struct timevar_stack_def *)
+ xmalloc (sizeof (struct timevar_stack_def));
+
+ /* Fill it in and put it on the stack. */
context->timevar = tv;
context->next = stack;
stack = context;
timevar_id_t timevar;
{
struct timevar_time_def now;
- struct timevar_stack_def *next = stack->next;
+ struct timevar_stack_def *popped = stack;
+
+ if (!TIMEVAR_ENABLE)
+ return;
if (&timevars[timevar] != stack->timevar)
abort ();
get_time (&now);
/* Attribute the elapsed time to the element we're popping. */
- timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
+ timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
/* Reset the start time; from now on, time is attributed to the
element just exposed on the stack. */
start_time = now;
- /* Remove the stack element. */
- free (stack);
- stack = next;
+ /* 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;
}
/* Start timing TIMEVAR independently of the timing stack. Elapsed
{
struct timevar_def *tv = &timevars[timevar];
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
/* Don't allow the same timing variable to be started more than
once. */
if (tv->standalone)
struct timevar_def *tv = &timevars[timevar];
struct timevar_time_def now;
+ if (!TIMEVAR_ENABLE)
+ return;
+
/* TIMEVAR must have been started via timevar_start. */
if (!tv->standalone)
abort ();
timevar_id_t id;
struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
+ if (!TIMEVAR_ENABLE)
+ return;
+
fprintf (fp, "\nExecution times (seconds)\n");
for (id = 0; id < TIMEVAR_LAST; ++id)
{
if (id == TV_TOTAL)
continue;
+ /* Don't print timing variables that were never used. */
+ if (!tv->used)
+ continue;
+
/* The timing variable name. */
fprintf (fp, " %-22s:", tv->name);
all_time == 0 ? 0
: (long) (((100.0 * (double) total) / (double) all_time) + .5));
}
-