Message ID | 3c91e664-8624-aa73-1ebc-9fcaef1feb00@suse.cz |
---|---|
State | New |
Headers | show |
Series | Restore init_ggc_heuristics. | expand |
> 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 (); >
On 11/18/19 2:08 PM, Jan Hubicka wrote: > 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. I verified that by printing the values in gcc_collect: 2180 void 2181 ggc_collect (void) 2182 { 2183 /* Avoid frequent unnecessary work by skipping collection if the 2184 total allocations haven't expanded much since the last 2185 collection. */ 2186 float allocated_last_gc = 2187 MAX (G.allocated_last_gc, (size_t)param_ggc_min_heapsize * 1024); Martin
On Mon, Nov 18, 2019 at 1:24 PM Martin Liška <mliska@suse.cz> wrote: > > 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? > > Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > > Ready to be installed? I prefer to _not_ move all the functions. Moving the init_ggc_heuristics call is OK. Thanks, Richard. > 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(-) > >
On 11/19/19 11:03 AM, Richard Biener wrote: > On Mon, Nov 18, 2019 at 1:24 PM Martin Liška <mliska@suse.cz> wrote: >> >> 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? >> >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests. >> >> Ready to be installed? > > I prefer to _not_ move all the functions. Moving the init_ggc_heuristics > call is OK. I would like to, but opts.o is also put into all wrappers: g++ -no-pie -g -DIN_GCC -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common -DHAVE_CONFIG_H -static-libstdc++ -static-libgcc -o xgcc gcc.o gcc-main.o ggc-none.o \ c/gccspec.o driver-i386.o libcommon-target.a \ libcommon.a ../libcpp/libcpp.a ../libbacktrace/.libs/libbacktrace.a ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: libcommon-target.a(opts.o): in function `init_options_struct(gcc_options*, gcc_options*)': /home/marxin/Programming/gcc/gcc/opts.c:292: undefined reference to `init_ggc_heuristics()' collect2: error: ld returned 1 exit status make: *** [Makefile:2037: xgcc] Error 1 and adding ggc-common.o to OBJS-libcommon-target will not work. That's why I also moved the implementation. Martin > > Thanks, > Richard. > >> 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(-) >> >>
On Tue, Nov 19, 2019 at 12:37 PM Martin Liška <mliska@suse.cz> wrote: > > On 11/19/19 11:03 AM, Richard Biener wrote: > > On Mon, Nov 18, 2019 at 1:24 PM Martin Liška <mliska@suse.cz> wrote: > >> > >> 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? > >> > >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > >> > >> Ready to be installed? > > > > I prefer to _not_ move all the functions. Moving the init_ggc_heuristics > > call is OK. > > I would like to, but opts.o is also put into all wrappers: > > g++ -no-pie -g -DIN_GCC -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common -DHAVE_CONFIG_H -static-libstdc++ -static-libgcc -o xgcc gcc.o gcc-main.o ggc-none.o \ > c/gccspec.o driver-i386.o libcommon-target.a \ > libcommon.a ../libcpp/libcpp.a ../libbacktrace/.libs/libbacktrace.a ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a > /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: libcommon-target.a(opts.o): in function `init_options_struct(gcc_options*, gcc_options*)': > /home/marxin/Programming/gcc/gcc/opts.c:292: undefined reference to `init_ggc_heuristics()' > collect2: error: ld returned 1 exit status > make: *** [Makefile:2037: xgcc] Error 1 > > and adding ggc-common.o to OBJS-libcommon-target will not work. > That's why I also moved the implementation. Well, then call it from the caller of init_options_struct instead, right after it or after the langhook variant is called? Richard. > > Martin > > > > > Thanks, > > Richard. > > > >> 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(-) > >> > >> >
On 11/19/19 1:42 PM, Richard Biener wrote: > Well, then call it from the caller of init_options_struct instead, > right after it or after the > langhook variant is called? Yes, that's definitely possible, there's a patch that I've just locally tested. Ready for trunk? Thanks, Martin
On Tue, Nov 19, 2019 at 2:18 PM Martin Liška <mliska@suse.cz> wrote: > > On 11/19/19 1:42 PM, Richard Biener wrote: > > Well, then call it from the caller of init_options_struct instead, > > right after it or after the > > langhook variant is called? > > Yes, that's definitely possible, there's a patch that I've just locally tested. > > Ready for trunk? OK. > Thanks, > Martin
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 ();