[PATCH] Restore init_ggc_heuristics.

Jan Hubicka hubicka@ucw.cz
Mon Nov 18 13:09:00 GMT 2019


> Hello.
> 
> After my param to option transformation, we lost automatic GGC
> detection. It's because init_ggc_heuristics is called before
> init_options_struct which memsets all the values to zero first.
> 
> I've tested the patch with --enable-checking=release and I hope
> Honza can test it more?

You should be able to measure the difference building tramp3d on
enable-checking=release compiler.  I will include the patch in my next
round of Firefox benchmark (probably tonight) unless you beat me.

Honza
> 
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> 
> Ready to be installed?
> Thanks,
> Martin
> 
> gcc/ChangeLog:
> 
> 2019-11-18  Martin Liska  <mliska@suse.cz>
> 
> 	* ggc-common.c (ggc_rlimit_bound): Move to opts.c
> 	(ggc_min_expand_heuristic): Likewise.
> 	(ggc_min_heapsize_heuristic): Likewise.
> 	(init_ggc_heuristics): Likewise.
> 	* ggc.h (init_ggc_heuristics): Remove declaration.
> 	* opts.c (ggc_rlimit_bound): Moved here from ggc-common.c.
> 	(ggc_min_expand_heuristic): Likewise.
> 	(ggc_min_heapsize_heuristic): Likewise.
> 	(init_ggc_heuristics): Likewise.
> 	(init_options_struct): Init GGC params.
> 	* toplev.c (general_init): Remove call to init_ggc_heuristics.
> ---
>  gcc/ggc-common.c | 103 ---------------------------------------------
>  gcc/ggc.h        |   3 --
>  gcc/opts.c       | 106 +++++++++++++++++++++++++++++++++++++++++++++++
>  gcc/toplev.c     |   4 --
>  4 files changed, 106 insertions(+), 110 deletions(-)
> 
> 

> diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> index f6e393d7bb6..86aab015b91 100644
> --- a/gcc/ggc-common.c
> +++ b/gcc/ggc-common.c
> @@ -715,109 +715,6 @@ mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
>  }
>  #endif /* HAVE_MMAP_FILE */
>  
> -#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
> -
> -/* Modify the bound based on rlimits.  */
> -static double
> -ggc_rlimit_bound (double limit)
> -{
> -#if defined(HAVE_GETRLIMIT)
> -  struct rlimit rlim;
> -# if defined (RLIMIT_AS)
> -  /* RLIMIT_AS is what POSIX says is the limit on mmap.  Presumably
> -     any OS which has RLIMIT_AS also has a working mmap that GCC will use.  */
> -  if (getrlimit (RLIMIT_AS, &rlim) == 0
> -      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
> -      && rlim.rlim_cur < limit)
> -    limit = rlim.rlim_cur;
> -# elif defined (RLIMIT_DATA)
> -  /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
> -     might be on an OS that has a broken mmap.  (Others don't bound
> -     mmap at all, apparently.)  */
> -  if (getrlimit (RLIMIT_DATA, &rlim) == 0
> -      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
> -      && rlim.rlim_cur < limit
> -      /* Darwin has this horribly bogus default setting of
> -	 RLIMIT_DATA, to 6144Kb.  No-one notices because RLIMIT_DATA
> -	 appears to be ignored.  Ignore such silliness.  If a limit
> -	 this small was actually effective for mmap, GCC wouldn't even
> -	 start up.  */
> -      && rlim.rlim_cur >= 8 * 1024 * 1024)
> -    limit = rlim.rlim_cur;
> -# endif /* RLIMIT_AS or RLIMIT_DATA */
> -#endif /* HAVE_GETRLIMIT */
> -
> -  return limit;
> -}
> -
> -/* Heuristic to set a default for GGC_MIN_EXPAND.  */
> -static int
> -ggc_min_expand_heuristic (void)
> -{
> -  double min_expand = physmem_total ();
> -
> -  /* Adjust for rlimits.  */
> -  min_expand = ggc_rlimit_bound (min_expand);
> -
> -  /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
> -     a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB).  */
> -  min_expand /= 1024*1024*1024;
> -  min_expand *= 70;
> -  min_expand = MIN (min_expand, 70);
> -  min_expand += 30;
> -
> -  return min_expand;
> -}
> -
> -/* Heuristic to set a default for GGC_MIN_HEAPSIZE.  */
> -static int
> -ggc_min_heapsize_heuristic (void)
> -{
> -  double phys_kbytes = physmem_total ();
> -  double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
> -
> -  phys_kbytes /= 1024; /* Convert to Kbytes.  */
> -  limit_kbytes /= 1024;
> -
> -  /* The heuristic is RAM/8, with a lower bound of 4M and an upper
> -     bound of 128M (when RAM >= 1GB).  */
> -  phys_kbytes /= 8;
> -
> -#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
> -  /* Try not to overrun the RSS limit while doing garbage collection.
> -     The RSS limit is only advisory, so no margin is subtracted.  */
> - {
> -   struct rlimit rlim;
> -   if (getrlimit (RLIMIT_RSS, &rlim) == 0
> -       && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
> -     phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
> - }
> -# endif
> -
> -  /* Don't blindly run over our data limit; do GC at least when the
> -     *next* GC would be within 20Mb of the limit or within a quarter of
> -     the limit, whichever is larger.  If GCC does hit the data limit,
> -     compilation will fail, so this tries to be conservative.  */
> -  limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
> -  limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
> -  phys_kbytes = MIN (phys_kbytes, limit_kbytes);
> -
> -  phys_kbytes = MAX (phys_kbytes, 4 * 1024);
> -  phys_kbytes = MIN (phys_kbytes, 128 * 1024);
> -
> -  return phys_kbytes;
> -}
> -#endif
> -
> -void
> -init_ggc_heuristics (void)
> -{
> -#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
> -  param_ggc_min_expand = ggc_min_expand_heuristic ();
> -  param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
> -#endif
> -}
> -
>  /* GGC memory usage.  */
>  class ggc_usage: public mem_usage
>  {
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 6c64caaafb2..04431439c5e 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -285,9 +285,6 @@ extern void ggc_print_statistics (void);
>  
>  extern void stringpool_statistics (void);
>  
> -/* Heuristics.  */
> -extern void init_ggc_heuristics (void);
> -
>  /* Report current heap memory use to stderr.  */
>  extern void report_heap_memory_use (void);
>  
> diff --git a/gcc/opts.c b/gcc/opts.c
> index addebf15365..7e363e5c1d6 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -275,6 +275,110 @@ init_opts_obstack (void)
>    gcc_obstack_init (&opts_obstack);
>  }
>  
> +#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
> +
> +/* Modify the bound based on rlimits.  */
> +
> +static double
> +ggc_rlimit_bound (double limit)
> +{
> +#if defined(HAVE_GETRLIMIT)
> +  struct rlimit rlim;
> +#if defined(RLIMIT_AS)
> +  /* RLIMIT_AS is what POSIX says is the limit on mmap.  Presumably
> +     any OS which has RLIMIT_AS also has a working mmap that GCC will use.  */
> +  if (getrlimit (RLIMIT_AS, &rlim) == 0
> +      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY && rlim.rlim_cur < limit)
> +    limit = rlim.rlim_cur;
> +#elif defined(RLIMIT_DATA)
> +  /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
> +     might be on an OS that has a broken mmap.  (Others don't bound
> +     mmap at all, apparently.)  */
> +  if (getrlimit (RLIMIT_DATA, &rlim) == 0
> +      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
> +      && rlim.rlim_cur < limit
> +      /* Darwin has this horribly bogus default setting of
> +	 RLIMIT_DATA, to 6144Kb.  No-one notices because RLIMIT_DATA
> +	 appears to be ignored.  Ignore such silliness.  If a limit
> +	 this small was actually effective for mmap, GCC wouldn't even
> +	 start up.  */
> +      && rlim.rlim_cur >= 8 * 1024 * 1024)
> +    limit = rlim.rlim_cur;
> +#endif /* RLIMIT_AS or RLIMIT_DATA */
> +#endif /* HAVE_GETRLIMIT */
> +
> +  return limit;
> +}
> +
> +/* Heuristic to set a default for GGC_MIN_EXPAND.  */
> +
> +static int
> +ggc_min_expand_heuristic (void)
> +{
> +  double min_expand = physmem_total ();
> +
> +  /* Adjust for rlimits.  */
> +  min_expand = ggc_rlimit_bound (min_expand);
> +
> +  /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
> +     a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB).  */
> +  min_expand /= 1024 * 1024 * 1024;
> +  min_expand *= 70;
> +  min_expand = MIN (min_expand, 70);
> +  min_expand += 30;
> +
> +  return min_expand;
> +}
> +
> +/* Heuristic to set a default for GGC_MIN_HEAPSIZE.  */
> +static int
> +ggc_min_heapsize_heuristic (void)
> +{
> +  double phys_kbytes = physmem_total ();
> +  double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
> +
> +  phys_kbytes /= 1024; /* Convert to Kbytes.  */
> +  limit_kbytes /= 1024;
> +
> +  /* The heuristic is RAM/8, with a lower bound of 4M and an upper
> +     bound of 128M (when RAM >= 1GB).  */
> +  phys_kbytes /= 8;
> +
> +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_RSS)
> +  /* Try not to overrun the RSS limit while doing garbage collection.
> +     The RSS limit is only advisory, so no margin is subtracted.  */
> +  {
> +    struct rlimit rlim;
> +    if (getrlimit (RLIMIT_RSS, &rlim) == 0
> +	&& rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
> +      phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
> +  }
> +#endif
> +
> +  /* Don't blindly run over our data limit; do GC at least when the
> +     *next* GC would be within 20Mb of the limit or within a quarter of
> +     the limit, whichever is larger.  If GCC does hit the data limit,
> +     compilation will fail, so this tries to be conservative.  */
> +  limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
> +  limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
> +  phys_kbytes = MIN (phys_kbytes, limit_kbytes);
> +
> +  phys_kbytes = MAX (phys_kbytes, 4 * 1024);
> +  phys_kbytes = MIN (phys_kbytes, 128 * 1024);
> +
> +  return phys_kbytes;
> +}
> +#endif
> +
> +static void
> +init_ggc_heuristics (void)
> +{
> +#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
> +  param_ggc_min_expand = ggc_min_expand_heuristic ();
> +  param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
> +#endif
> +}
> +
>  /* Initialize OPTS and OPTS_SET before using them in parsing options.  */
>  
>  void
> @@ -289,6 +393,8 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
>    if (opts_set)
>      memset (opts_set, 0, sizeof (*opts_set));
>  
> +  init_ggc_heuristics ();
> +
>    /* Initialize whether `char' is signed.  */
>    opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
>    /* Set this to a special "uninitialized" value.  The actual default
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index d4583bac66c..fa6d39355d0 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -1240,10 +1240,6 @@ general_init (const char *argv0, bool init_signals)
>    /* Initialize register usage now so switches may override.  */
>    init_reg_sets ();
>  
> -  /* This must be done after global_init_params but before argument
> -     processing.  */
> -  init_ggc_heuristics ();
> -
>    /* Create the singleton holder for global state.  This creates the
>       dump manager.  */
>    g = new gcc::context ();
> 



More information about the Gcc-patches mailing list