00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "intl.h"
00029 #include "rtl.h"
00030
00031 #ifdef HAVE_SYS_TIMES_H
00032 # include <sys/times.h>
00033 #endif
00034 #ifdef HAVE_SYS_RESOURCE_H
00035 #include <sys/resource.h>
00036 #endif
00037
00038 #ifndef SGI_MONGOOSE
00039
00040 #ifndef HAVE_CLOCK_T
00041 typedef int clock_t;
00042 #endif
00043 #endif
00044
00045 #ifndef SGI_MONGOOSE
00046
00047 #ifndef HAVE_STRUCT_TMS
00048 struct tms
00049 {
00050 clock_t tms_utime;
00051 clock_t tms_stime;
00052 clock_t tms_cutime;
00053 clock_t tms_cstime;
00054 };
00055 #endif
00056 #endif
00057
00058 #if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
00059 extern int getrusage PARAMS ((int, struct rusage *));
00060 #endif
00061 #if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
00062 extern clock_t times PARAMS ((struct tms *));
00063 #endif
00064 #if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
00065 extern clock_t clock PARAMS ((void));
00066 #endif
00067
00068 #ifndef RUSAGE_SELF
00069 # define RUSAGE_SELF 0
00070 #endif
00071
00072
00073
00074 #if HAVE_SYSCONF && defined _SC_CLK_TCK
00075 # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK)
00076 #else
00077 # ifdef CLK_TCK
00078 # define TICKS_PER_SECOND CLK_TCK
00079 # else
00080 # ifdef HZ
00081 # define TICKS_PER_SECOND HZ
00082 # else
00083 # define TICKS_PER_SECOND 100
00084 # endif
00085 # endif
00086 #endif
00087
00088
00089
00090 #ifdef HAVE_TIMES
00091 # define USE_TIMES
00092 # define HAVE_USER_TIME
00093 # define HAVE_SYS_TIME
00094 # define HAVE_WALL_TIME
00095 #else
00096 #ifdef HAVE_GETRUSAGE
00097 # define USE_GETRUSAGE
00098 # define HAVE_USER_TIME
00099 # define HAVE_SYS_TIME
00100 #else
00101 #ifdef HAVE_CLOCK
00102 # define USE_CLOCK
00103 # define HAVE_USER_TIME
00104 #endif
00105 #endif
00106 #endif
00107
00108
00109
00110
00111
00112 #ifdef USE_TIMES
00113 static float ticks_to_msec;
00114 #define TICKS_TO_MSEC (1 / (float)TICKS_PER_SECOND)
00115 #endif
00116
00117 #ifdef USE_CLOCK
00118 static float clocks_to_msec;
00119 #define CLOCKS_TO_MSEC (1 / (float)CLOCKS_PER_SEC)
00120 #endif
00121
00122 #include "flags.h"
00123 #include "timevar.h"
00124 #include "toplev.h"
00125
00126
00127
00128
00129 #define TIMEVAR_ENABLE (time_report)
00130
00131
00132
00133 struct timevar_def
00134 {
00135
00136 struct timevar_time_def elapsed;
00137
00138
00139
00140 struct timevar_time_def start_time;
00141
00142
00143 const char *name;
00144
00145
00146
00147 unsigned standalone : 1;
00148
00149
00150
00151 unsigned used : 1;
00152 };
00153
00154
00155
00156
00157 struct timevar_stack_def
00158 {
00159
00160 struct timevar_def *timevar;
00161
00162
00163 struct timevar_stack_def *next;
00164 };
00165
00166
00167
00168 static struct timevar_def timevars[TIMEVAR_LAST];
00169
00170
00171 static struct timevar_stack_def *stack;
00172
00173
00174
00175 static struct timevar_stack_def *unused_stack_instances;
00176
00177
00178
00179
00180 static struct timevar_time_def start_time;
00181
00182 static void get_time
00183 PARAMS ((struct timevar_time_def *));
00184 static void timevar_accumulate
00185 PARAMS ((struct timevar_time_def *, struct timevar_time_def *,
00186 struct timevar_time_def *));
00187
00188
00189
00190
00191
00192 static void
00193 get_time (now)
00194 struct timevar_time_def *now;
00195 {
00196 now->user = 0;
00197 now->sys = 0;
00198 now->wall = 0;
00199
00200 if (!TIMEVAR_ENABLE)
00201 return;
00202
00203 {
00204 #ifdef USE_TIMES
00205 struct tms tms;
00206 now->wall = times (&tms) * ticks_to_msec;
00207 now->user = tms.tms_utime * ticks_to_msec;
00208 now->sys = tms.tms_stime * ticks_to_msec;
00209 #endif
00210 #ifdef USE_GETRUSAGE
00211 struct rusage rusage;
00212 getrusage (RUSAGE_SELF, &rusage);
00213 now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
00214 now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
00215 #endif
00216 #ifdef USE_CLOCK
00217 now->user = clock () * clocks_to_msec;
00218 #endif
00219 }
00220 }
00221
00222
00223
00224 static void
00225 timevar_accumulate (timer, start_time, stop_time)
00226 struct timevar_time_def *timer;
00227 struct timevar_time_def *start_time;
00228 struct timevar_time_def *stop_time;
00229 {
00230 timer->user += stop_time->user - start_time->user;
00231 timer->sys += stop_time->sys - start_time->sys;
00232 timer->wall += stop_time->wall - start_time->wall;
00233 }
00234
00235
00236
00237 void
00238 init_timevar ()
00239 {
00240 if (!TIMEVAR_ENABLE)
00241 return;
00242
00243
00244 memset ((void *) timevars, 0, sizeof (timevars));
00245
00246
00247 #define DEFTIMEVAR(identifier__, name__) \
00248 timevars[identifier__].name = name__;
00249 #include "timevar.def"
00250 #undef DEFTIMEVAR
00251
00252 #ifdef USE_TIMES
00253 ticks_to_msec = TICKS_TO_MSEC;
00254 #endif
00255 #ifdef USE_CLOCK
00256 clocks_to_msec = CLOCKS_TO_MSEC;
00257 #endif
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267 void
00268 timevar_push (timevar)
00269 timevar_id_t timevar;
00270 {
00271 struct timevar_def *tv = &timevars[timevar];
00272 struct timevar_stack_def *context;
00273 struct timevar_time_def now;
00274
00275 if (!TIMEVAR_ENABLE)
00276 return;
00277
00278
00279 tv->used = 1;
00280
00281
00282 if (tv->standalone)
00283 abort ();
00284
00285
00286 get_time (&now);
00287
00288
00289
00290 if (stack)
00291 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
00292
00293
00294
00295 start_time = now;
00296
00297
00298
00299 if (unused_stack_instances != NULL)
00300 {
00301 context = unused_stack_instances;
00302 unused_stack_instances = unused_stack_instances->next;
00303 }
00304 else
00305 context = (struct timevar_stack_def *)
00306 xmalloc (sizeof (struct timevar_stack_def));
00307
00308
00309 context->timevar = tv;
00310 context->next = stack;
00311 stack = context;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 void
00321 timevar_pop (timevar)
00322 timevar_id_t timevar;
00323 {
00324 struct timevar_time_def now;
00325 struct timevar_stack_def *popped = stack;
00326
00327 if (!TIMEVAR_ENABLE)
00328 return;
00329
00330 if (&timevars[timevar] != stack->timevar)
00331 {
00332 sorry ("cannot timevar_pop '%s' when top of timevars stack is '%s'",
00333 timevars[timevar].name, stack->timevar->name);
00334 abort ();
00335 }
00336
00337
00338 get_time (&now);
00339
00340
00341 timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
00342
00343
00344
00345 start_time = now;
00346
00347
00348 stack = stack->next;
00349
00350
00351
00352 popped->next = unused_stack_instances;
00353 unused_stack_instances = popped;
00354 }
00355
00356
00357
00358
00359
00360 void
00361 timevar_start (timevar)
00362 timevar_id_t timevar;
00363 {
00364 struct timevar_def *tv = &timevars[timevar];
00365
00366 if (!TIMEVAR_ENABLE)
00367 return;
00368
00369
00370 tv->used = 1;
00371
00372
00373
00374 if (tv->standalone)
00375 abort ();
00376 tv->standalone = 1;
00377
00378 get_time (&tv->start_time);
00379 }
00380
00381
00382
00383
00384 void
00385 timevar_stop (timevar)
00386 timevar_id_t timevar;
00387 {
00388 struct timevar_def *tv = &timevars[timevar];
00389 struct timevar_time_def now;
00390
00391 if (!TIMEVAR_ENABLE)
00392 return;
00393
00394
00395 if (!tv->standalone)
00396 abort ();
00397
00398 get_time (&now);
00399 timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
00400 }
00401
00402
00403
00404
00405 void
00406 timevar_get (timevar, elapsed)
00407 timevar_id_t timevar;
00408 struct timevar_time_def *elapsed;
00409 {
00410 struct timevar_def *tv = &timevars[timevar];
00411 struct timevar_time_def now;
00412
00413 *elapsed = tv->elapsed;
00414
00415
00416 if (tv->standalone)
00417 {
00418 get_time (&now);
00419 timevar_accumulate (elapsed, &tv->start_time, &now);
00420 }
00421
00422 else if (stack->timevar == tv)
00423 {
00424 get_time (&now);
00425 timevar_accumulate (elapsed, &start_time, &now);
00426 }
00427 }
00428
00429
00430
00431
00432
00433 void
00434 timevar_print (fp)
00435 FILE *fp;
00436 {
00437
00438 #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
00439 unsigned int id;
00440 struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
00441 struct timevar_time_def now;
00442
00443 if (!TIMEVAR_ENABLE)
00444 return;
00445
00446
00447
00448 if (fp == 0)
00449 fp = stderr;
00450
00451
00452 get_time (&now);
00453
00454
00455
00456 if (stack)
00457 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
00458
00459
00460
00461 start_time = now;
00462
00463 fputs (_("\nExecution times (seconds)\n"), fp);
00464 for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
00465 {
00466 struct timevar_def *tv = &timevars[(timevar_id_t) id];
00467 const float tiny = 5e-3;
00468
00469
00470
00471 if ((timevar_id_t) id == TV_TOTAL)
00472 continue;
00473
00474
00475 if (!tv->used)
00476 continue;
00477
00478
00479
00480 if (tv->elapsed.user < tiny
00481 && tv->elapsed.sys < tiny
00482 && tv->elapsed.wall < tiny)
00483 continue;
00484
00485
00486 fprintf (fp, " %-22s:", tv->name);
00487
00488 #ifdef HAVE_USER_TIME
00489
00490 fprintf (fp, "%7.2f (%2.0f%%) usr",
00491 tv->elapsed.user,
00492 (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
00493 #endif
00494
00495 #ifdef HAVE_SYS_TIME
00496
00497 fprintf (fp, "%7.2f (%2.0f%%) sys",
00498 tv->elapsed.sys,
00499 (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
00500 #endif
00501
00502 #ifdef HAVE_WALL_TIME
00503
00504 fprintf (fp, "%7.2f (%2.0f%%) wall",
00505 tv->elapsed.wall,
00506 (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
00507 #endif
00508
00509 putc ('\n', fp);
00510 }
00511
00512
00513 fputs (_(" TOTAL :"), fp);
00514 #ifdef HAVE_USER_TIME
00515 fprintf (fp, "%7.2f ", total->user);
00516 #endif
00517 #ifdef HAVE_SYS_TIME
00518 fprintf (fp, "%7.2f ", total->sys);
00519 #endif
00520 #ifdef HAVE_WALL_TIME
00521 fprintf (fp, "%7.2f\n", total->wall);
00522 #endif
00523
00524 #endif
00525
00526 }
00527
00528
00529
00530
00531 long
00532 get_run_time ()
00533 {
00534 struct timevar_time_def total_elapsed;
00535 timevar_get (TV_TOTAL, &total_elapsed);
00536 return total_elapsed.user + total_elapsed.sys;
00537 }
00538
00539
00540
00541
00542 void
00543 print_time (str, total)
00544 const char *str;
00545 long total;
00546 {
00547 long all_time = get_run_time ();
00548 fprintf (stderr,
00549 _("time in %s: %ld.%06ld (%ld%%)\n"),
00550 str, total / 1000000, total % 1000000,
00551 all_time == 0 ? 0
00552 : (long) (((100.0 * (double) total) / (double) all_time) + .5));
00553 }