On Wed, Oct 9, 2024 at 6:18 PM Andi Kleen <a...@linux.intel.com> wrote:
>
> From: Andi Kleen <a...@gcc.gnu.org>
>
> Retrieving sys/user time in timevars is quite expensive because it
> always needs a system call. Only getting the wall time is much
> cheaper because operating systems have optimized paths for this.
>
> The sys time isn't that interesting for a compiler and wall time
> is usually close to user time except when the system is overloaded.
> On the other hand when it is not wall time is more accurate because
> it has less overhead.
>
> For building tramp3d with -O0 the -ftime-report overhead drops from
> 18% to 3%. For -O2 it drops from 8% to not measurable.
>
> I changed the code to use gettimeofday as a fallback for clock_gettime
> CLOCK_MONOTONIC.  If a host has neither of those the time will not
> be measured. Previously clock was the fallback.

OK for trunk if there's no serious objection until mid next week.

Richard.

> This removes a lot of code in timevar.cc:
>
>  gcc/timevar.cc | 167 
> ++++++---------------------------------------------------
>  gcc/timevar.h  |  10 +---
>
>  2 files changed, 17 insertions(+), 160 deletions(-)
>
> Bootstrapped on x86_64-linux with full test suite run.
>
> gcc/ChangeLog:
>
>         * timevar.cc (struct tms): Remove.
>         (RUSAGE_SELF): Remove.
>         (TICKS_PER_SECOND): Remove.
>         (USE_TIMES): Remove.
>         (HAVE_USER_TIME): Remove.
>         (HAVE_SYS_TIME): Remove.
>         (HAVE_WALL_TIME): Remove.
>         (USE_GETRUSAGE): Remove.
>         (USE_CLOCK): Remove.
>         (NANOSEC_PER_SEC): Remove.
>         (TICKS_TO_NANOSEC): Remove.
>         (CLOCKS_TO_NANOSEC): Remove.
>         (timer::named_items::push): Remove sys/user.
>         (get_time): Remove clock and times and getruage code.
>         (timevar_accumulate): Remove sys/user.
>         (timevar_diff): Dito.
>         (timer::validate_phases): Dito.
>         (timer::print_row): Dito.
>         (timer::all_zero): Dito.
>         (timer::print): Dito.
>         (make_json_for_timevar_time_def): Dito.
>         * timevar.h (struct timevar_time_def): Dito.
>
> ---
>
> v2: Adjust JSON/Sarif output too.
> v3: Make unconditional.
> ---
>  gcc/timevar.cc | 189 ++++++-------------------------------------------
>  gcc/timevar.h  |  10 +--
>  2 files changed, 22 insertions(+), 177 deletions(-)
>
> diff --git a/gcc/timevar.cc b/gcc/timevar.cc
> index 68bcf44864f9..4a57e74230d3 100644
> --- a/gcc/timevar.cc
> +++ b/gcc/timevar.cc
> @@ -26,84 +26,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "options.h"
>  #include "json.h"
>
> -#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 seconds.
> -   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
> -# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
> -  extern clock_t times (struct tms *);
> -# endif
> -# define USE_TIMES
> -# define HAVE_USER_TIME
> -# define HAVE_SYS_TIME
> -# define HAVE_WALL_TIME
> -#else
> -#ifdef HAVE_GETRUSAGE
> -# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
> -  extern int getrusage (int, struct rusage *);
> -# endif
> -# define USE_GETRUSAGE
> -# define HAVE_USER_TIME
> -# define HAVE_SYS_TIME
> -#else
> -#ifdef HAVE_CLOCK
> -# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
> -  extern clock_t clock (void);
> -# endif
> -# define USE_CLOCK
> -# define HAVE_USER_TIME
> -#endif
> -#endif
> -#endif
> -
> -/* 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?  */
> -#define NANOSEC_PER_SEC 1000000000
> -#ifdef USE_TIMES
> -static uint64_t ticks_to_nanosec;
> -#define TICKS_TO_NANOSEC (NANOSEC_PER_SEC / TICKS_PER_SECOND)
> -#endif
> -
> -#ifdef USE_CLOCK
> -static uint64_t clocks_to_nanosec;
> -#define CLOCKS_TO_NANOSEC (NANOSEC_PER_SEC / CLOCKS_PER_SEC)
> -#endif
> -
>  /* Non-NULL if timevars should be used.  In GCC, this happens with
>     the -ftime-report flag.  */
>
> @@ -181,8 +103,6 @@ timer::named_items::push (const char *item_name)
>    timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
>    if (!existed)
>      {
> -      def->elapsed.user = 0;
> -      def->elapsed.sys = 0;
>        def->elapsed.wall = 0;
>        def->name = item_name;
>        def->standalone = 0;
> @@ -230,37 +150,27 @@ timer::named_items::make_json () const
>    return arr;
>  }
>
> -/* 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
> -   HAVE_WALL_TIME macros.  */
> +/* Fill the current times into TIME, and define HAVE_WALL_TIME if there.  */
>
>  static void
>  get_time (struct timevar_time_def *now)
>  {
> -  now->user = 0;
> -  now->sys  = 0;
>    now->wall = 0;
>    now->ggc_mem = timevar_ggc_mem_total;
>
> -  {
> -#ifdef USE_TIMES
> -    struct tms tms;
> -    now->wall = times (&tms)  * ticks_to_nanosec;
> -    now->user = tms.tms_utime * ticks_to_nanosec;
> -    now->sys  = tms.tms_stime * ticks_to_nanosec;
> -#endif
> -#ifdef USE_GETRUSAGE
> -    struct rusage rusage;
> -    getrusage (RUSAGE_SELF, &rusage);
> -    now->user = rusage.ru_utime.tv_sec * NANOSEC_PER_SEC
> -               + rusage.ru_utime.tv_usec * 1000;
> -    now->sys  = rusage.ru_stime.tv_sec * NANOSEC_PER_SEC
> -               + rusage.ru_stime.tv_usec * 1000;
> +#if _POSIX_C_SOURCE >= 199309L
> +  struct timespec ts;
> +  clock_gettime (CLOCK_MONOTONIC, &ts);
> +  now->wall = ts.tv_sec * 1000000000 + ts.tv_nsec;
> +  return;
> +#define HAVE_WALL_TIME 1
>  #endif
> -#ifdef USE_CLOCK
> -    now->user = clock () * clocks_to_nanosec;
> +#ifdef HAVE_GETTIMEOFDAY
> +  struct timeval tv;
> +  gettimeofday (&tv, NULL);
> +  now->wall = tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
> +#define HAVE_WALL_TIME 1
>  #endif
> -  }
>  }
>
>  /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
> @@ -270,8 +180,6 @@ timevar_accumulate (struct timevar_time_def *timer,
>                     struct timevar_time_def *start_time,
>                     struct timevar_time_def *stop_time)
>  {
> -  timer->user += stop_time->user - start_time->user;
> -  timer->sys += stop_time->sys - start_time->sys;
>    timer->wall += stop_time->wall - start_time->wall;
>    timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
>  }
> @@ -283,8 +191,6 @@ timevar_diff (struct timevar_time_def *out,
>               const timevar_time_def &start_time,
>               const timevar_time_def &stop_time)
>  {
> -  out->user = stop_time.user - start_time.user;
> -  out->sys = stop_time.sys - start_time.sys;
>    out->wall = stop_time.wall - start_time.wall;
>    out->ggc_mem = stop_time.ggc_mem - start_time.ggc_mem;
>  }
> @@ -305,15 +211,6 @@ timer::timer () :
>    m_timevars[identifier__].name = name__;
>  #include "timevar.def"
>  #undef DEFTIMEVAR
> -
> -  /* Initialize configuration-specific state.
> -     Ideally this would be one-time initialization.  */
> -#ifdef USE_TIMES
> -  ticks_to_nanosec = TICKS_TO_NANOSEC;
> -#endif
> -#ifdef USE_CLOCK
> -  clocks_to_nanosec = CLOCKS_TO_NANOSEC;
> -#endif
>  }
>
>  /* Class timer's destructor.  */
> @@ -621,8 +518,6 @@ timer::validate_phases (FILE *fp) const
>  {
>    unsigned int /* timevar_id_t */ id;
>    const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
> -  uint64_t phase_user = 0;
> -  uint64_t phase_sys = 0;
>    uint64_t phase_wall = 0;
>    size_t phase_ggc_mem = 0;
>    static char phase_prefix[] = "phase ";
> @@ -637,26 +532,15 @@ timer::validate_phases (FILE *fp) const
>
>        if (startswith (tv->name, phase_prefix))
>         {
> -         phase_user += tv->elapsed.user;
> -         phase_sys += tv->elapsed.sys;
>           phase_wall += tv->elapsed.wall;
>           phase_ggc_mem += tv->elapsed.ggc_mem;
>         }
>      }
>
> -  if (phase_user > total->user
> -      || phase_sys > total->sys
> -      || phase_wall > total->wall
> -      || phase_ggc_mem > total->ggc_mem)
> +  if (phase_wall > total->wall || phase_ggc_mem > total->ggc_mem)
>      {
>
>        fprintf (fp, "Timing error: total of phase timers exceeds total 
> time.\n");
> -      if (phase_user > total->user)
> -       fprintf (fp, "user    %13" PRIu64 " > %13" PRIu64 "\n",
> -                phase_user, total->user);
> -      if (phase_sys > total->sys)
> -       fprintf (fp, "sys     %13" PRIu64 " > %13" PRIu64 "\n",
> -                phase_sys, total->sys);
>        if (phase_wall > total->wall)
>         fprintf (fp, "wall    %13" PRIu64 " > %13" PRIu64 "\n",
>                  phase_wall, total->wall);
> @@ -680,20 +564,6 @@ timer::print_row (FILE *fp,
>    /* The timing variable name.  */
>    fprintf (fp, " %-35s:", name);
>
> -#ifdef HAVE_USER_TIME
> -  /* Print user-mode time for this process.  */
> -  fprintf (fp, "%7.2f (%3.0f%%)",
> -          nanosec_to_floating_sec (elapsed.user),
> -          percent_of (total->user, elapsed.user));
> -#endif /* HAVE_USER_TIME */
> -
> -#ifdef HAVE_SYS_TIME
> -  /* Print system-mode time for this process.  */
> -  fprintf (fp, "%7.2f (%3.0f%%)",
> -          nanosec_to_floating_sec (elapsed.sys),
> -          percent_of (total->sys, elapsed.sys));
> -#endif /* HAVE_SYS_TIME */
> -
>  #ifdef HAVE_WALL_TIME
>    /* Print wall clock time elapsed.  */
>    fprintf (fp, "%7.2f (%3.0f%%)",
> @@ -718,9 +588,7 @@ timer::all_zero (const timevar_time_def &elapsed)
>  {
>    /* 5000000 nanosec == 5e-3 seconds.  */
>    uint64_t tiny = 5000000;
> -  return (elapsed.user < tiny
> -         && elapsed.sys < tiny
> -         && elapsed.wall < tiny
> +  return (elapsed.wall < tiny
>           && elapsed.ggc_mem < GGC_MEM_BOUND);
>  }
>
> @@ -732,7 +600,7 @@ void
>  timer::print (FILE *fp)
>  {
>    /* Only print stuff if we have some sort of time information.  */
> -#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined 
> (HAVE_WALL_TIME)
> +#if defined (HAVE_WALL_TIME)
>    unsigned int /* timevar_id_t */ id;
>    const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
>    struct timevar_time_def now;
> @@ -754,8 +622,7 @@ timer::print (FILE *fp)
>       TIMEVAR.  */
>    m_start_time = now;
>
> -  fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys",
> -          "wall", "GGC");
> +  fprintf (fp, "\n%-35s%16s%14s\n", "Time variable", "wall", "GGC");
>    if (m_jit_client_items)
>      fputs ("GCC items:\n", fp);
>    for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
> @@ -809,15 +676,7 @@ timer::print (FILE *fp)
>
>    /* Print total time.  */
>    fprintf (fp, " %-35s:", "TOTAL");
> -#ifdef HAVE_USER_TIME
> -  fprintf (fp, "%7.2f      ", nanosec_to_floating_sec (total->user));
> -#endif
> -#ifdef HAVE_SYS_TIME
> -  fprintf (fp, "%8.2f      ", nanosec_to_floating_sec (total->sys));
> -#endif
> -#ifdef HAVE_WALL_TIME
> -  fprintf (fp, "%8.2f      ", nanosec_to_floating_sec (total->wall));
> -#endif
> +  fprintf (fp, "%7.2f      ", nanosec_to_floating_sec (total->wall));
>    fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem));
>
>    if (CHECKING_P || flag_checking)
> @@ -829,8 +688,7 @@ timer::print (FILE *fp)
>    fprintf (fp, "Configure with --enable-checking=release to enable 
> checks.\n");
>  #endif
>
> -#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
> -         || defined (HAVE_WALL_TIME) */
> +#endif /* defined (HAVE_WALL_TIME) */
>
>    validate_phases (fp);
>  }
> @@ -842,8 +700,6 @@ json::object *
>  make_json_for_timevar_time_def (const timevar_time_def &ttd)
>  {
>    json::object *obj = new json::object ();
> -  obj->set_float ("user", nanosec_to_floating_sec (ttd.user));
> -  obj->set_float ("sys", nanosec_to_floating_sec (ttd.sys));
>    obj->set_float ("wall", nanosec_to_floating_sec (ttd.wall));
>    obj->set_integer ("ggc_mem", ttd.ggc_mem);
>    return obj;
> @@ -898,8 +754,7 @@ timer::timevar_def::make_json () const
>  json::value *
>  timer::make_json () const
>  {
> -  /* Only generate stuff if we have some sort of time information.  */
> -#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined 
> (HAVE_WALL_TIME)
> +#if defined (HAVE_WALL_TIME)
>    json::object *report_obj = new json::object ();
>    json::array *json_arr = new json::array ();
>    report_obj->set ("timevars", json_arr);
> @@ -958,11 +813,9 @@ timer::make_json () const
>
>    return report_obj;
>
> -#else /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
> -         || defined (HAVE_WALL_TIME) */
> +#else /* defined (HAVE_USER_TIME) */
>    return NULL;
> -#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
> -         || defined (HAVE_WALL_TIME) */
> +#endif /* !defined (HAVE_WALL_TIME) */
>  }
>
>  /* Get the name of the topmost item.  For use by jit for validating
> diff --git a/gcc/timevar.h b/gcc/timevar.h
> index c1fe2b5d5439..970ac53ce2a6 100644
> --- a/gcc/timevar.h
> +++ b/gcc/timevar.h
> @@ -24,9 +24,7 @@
>  namespace json { class value; }
>
>  /* Timing variables are used to measure elapsed time in various
> -   portions of the compiler.  Each measures elapsed user, system, and
> -   wall-clock time, as appropriate to and supported by the host
> -   system.
> +   portions of the compiler.  Each measures wall time.
>
>     Timing variables are defined using the DEFTIMEVAR macro in
>     timevar.def.  Each has an enumeral identifier, used when referring
> @@ -53,12 +51,6 @@ namespace json { class value; }
>
>  struct timevar_time_def
>  {
> -  /* User time in this process.  */
> -  uint64_t user;
> -
> -  /* System time (if applicable for this host platform) in this process.  */
> -  uint64_t sys;
> -
>    /* Wall clock time.  */
>    uint64_t wall;
>
> --
> 2.46.2
>

Reply via email to