This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/5] Use MADV_DONTNEED for freeing in garbage collector


On Sun, Oct 9, 2011 at 9:55 PM, Andi Kleen <andi@firstfloor.org> wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> Use the Linux MADV_DONTNEED call to unmap free pages in the garbage
> collector.Then keep the unmapped pages in the free list. This avoid
> excessive memory fragmentation on large LTO bulds, which can lead
> to gcc bumping into the Linux vm_max_map limit per process.
>
> Based on a idea from Jakub.

Shouldn't we prefer still "mapped" pages when allocating?  Thus, keep
the freepages list "sorted"?

With the new params to call release_pages less, how does this
interact with using MADV_DONTNEED?  The only reason to delay
MADV_DONTNEED is to avoid splitting huge-pages?  Which would
mean that we should rather be better at controlling where we allocate
from from the free-list?

Richard.

> gcc/:
>
> 2011-10-08 ? Andi Kleen <ak@linux.intel.com>
>
> ? ? ? ?PR other/50636
> ? ? ? ?* config.in, configure: Regenerate.
> ? ? ? ?* configure.ac (madvise): Add to AC_CHECK_FUNCS.
> ? ? ? ?* ggc-page.c (USING_MADVISE): Add.
> ? ? ? ?(page_entry): Add unmapped field.
> ? ? ? ?(alloc_page): Check for unmapped pages.
> ? ? ? ?(release_pages): Add USING_MADVISE branch.
> ---
> ?gcc/config.in ? ?| ? ?6 ++++++
> ?gcc/configure ? ?| ? ?2 +-
> ?gcc/configure.ac | ? ?2 +-
> ?gcc/ggc-page.c ? | ? 48 +++++++++++++++++++++++++++++++++++++++++++++++-
> ?4 files changed, 55 insertions(+), 3 deletions(-)
>
> diff --git a/gcc/config.in b/gcc/config.in
> index f2847d8..e8148b6 100644
> --- a/gcc/config.in
> +++ b/gcc/config.in
> @@ -1276,6 +1276,12 @@
> ?#endif
>
>
> +/* Define to 1 if you have the `madvise' function. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_MADVISE
> +#endif
> +
> +
> ?/* Define to 1 if you have the <malloc.h> header file. */
> ?#ifndef USED_FOR_TARGET
> ?#undef HAVE_MALLOC_H
> diff --git a/gcc/configure b/gcc/configure
> index cb55dda..4a54adf 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -9001,7 +9001,7 @@ fi
> ?for ac_func in times clock kill getrlimit setrlimit atoll atoq \
> ? ? ? ?sysconf strsignal getrusage nl_langinfo \
> ? ? ? ?gettimeofday mbstowcs wcswidth mmap setlocale \
> - ? ? ? clearerr_unlocked feof_unlocked ? ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked ? fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked ? fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked ? putchar_unlocked putc_unlocked
> + ? ? ? clearerr_unlocked feof_unlocked ? ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked ? fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked ? fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked ? putchar_unlocked putc_unlocked madvise
> ?do :
> ? as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
> ?ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index a7b94e6..357902e 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -1027,7 +1027,7 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
> ?AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoll atoq \
> ? ? ? ?sysconf strsignal getrusage nl_langinfo \
> ? ? ? ?gettimeofday mbstowcs wcswidth mmap setlocale \
> - ? ? ? gcc_UNLOCKED_FUNCS)
> + ? ? ? gcc_UNLOCKED_FUNCS madvise)
>
> ?if test x$ac_cv_func_mbstowcs = xyes; then
> ? AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
> diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
> index 624f029..b0b3b3f 100644
> --- a/gcc/ggc-page.c
> +++ b/gcc/ggc-page.c
> @@ -50,6 +50,10 @@ along with GCC; see the file COPYING3. ?If not see
> ?#define USING_MALLOC_PAGE_GROUPS
> ?#endif
>
> +#if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
> +# define USING_MADVISE
> +#endif
> +
> ?/* Strategy:
>
> ? ?This garbage-collecting allocator allocates objects on one of a set
> @@ -277,6 +281,9 @@ typedef struct page_entry
> ? /* The lg of size of objects allocated from this page. ?*/
> ? unsigned char order;
>
> + ?/* Unmapped page? */
> + ?bool unmapped;
> +
> ? /* A bit vector indicating whether or not objects are in use. ?The
> ? ? ?Nth bit is one if the Nth object on this page is allocated. ?This
> ? ? ?array is dynamically sized. ?*/
> @@ -740,6 +747,10 @@ alloc_page (unsigned order)
>
> ? if (p != NULL)
> ? ? {
> + ? ? ?if (p->unmapped)
> + ? ? ? ?G.bytes_mapped += p->bytes;
> + ? ? ?p->unmapped = false;
> +
> ? ? ? /* Recycle the allocated memory from this page ... ?*/
> ? ? ? *pp = p->next;
> ? ? ? page = p->page;
> @@ -956,7 +967,42 @@ free_page (page_entry *entry)
> ?static void
> ?release_pages (void)
> ?{
> -#ifdef USING_MMAP
> +#ifdef USING_MADVISE
> + ?page_entry *p, *start_p;
> + ?char *start;
> + ?size_t len;
> +
> + ?for (p = G.free_pages; p; )
> + ? ?{
> + ? ? ?if (p->unmapped)
> + ? ? ? ?{
> + ? ? ? ? ?p = p->next;
> + ? ? ? ? ?continue;
> + ? ? ? ?}
> + ? ? ?start = p->page;
> + ? ? ?len = p->bytes;
> + ? ? ?start_p = p;
> + ? ? ?p = p->next;
> + ? ? ?while (p && p->page == start + len)
> + ? ? ? ?{
> + ? ? ? ? ?len += p->bytes;
> + ? ? ? ? ?p = p->next;
> + ? ? ? ?}
> + ? ? ?/* Give the page back to the kernel, but don't free the mapping.
> + ? ? ? ? This avoids fragmentation in the virtual memory map of the
> + ? ? ? ?process. Next time we can reuse it by just touching it. */
> + ? ? ?madvise (start, len, MADV_DONTNEED);
> + ? ? ?/* Don't count those pages as mapped to not touch the garbage collector
> + ? ? ? ? unnecessarily. */
> + ? ? ?G.bytes_mapped -= len;
> + ? ? ?while (start_p != p)
> + ? ? ? ?{
> + ? ? ? ? ?start_p->unmapped = true;
> + ? ? ? ? ?start_p = start_p->next;
> + ? ? ? ?}
> + ? ?}
> +#endif
> +#if defined(USING_MMAP) && !defined(USING_MADVISE)
> ? page_entry *p, *next;
> ? char *start;
> ? size_t len;
> --
> 1.7.5.4
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]