From: Andi Kleen <a...@linux.intel.com>

Add a threshold to avoid freeing pages back too early to the OS.
This avoid virtual memory map fragmentation.

Based on a idea from Honza

ggc/doc/:

2011-10-08   Andi Kleen <a...@linux.intel.com>

        PR other/50636
        * invoke.texi (ggc-free-threshold, ggc-free-min): Add.

ggc/:

2011-10-08   Andi Kleen <a...@linux.intel.com>

        PR other/50636
        * ggc-page.c (ggc_collect): Add free threshold.
        * params.def (GGC_FREE_THRESHOLD, GGC_FREE_MIN): Add.
---
 gcc/doc/invoke.texi |   11 +++++++++++
 gcc/ggc-page.c      |   13 +++++++++----
 gcc/params.def      |   10 ++++++++++
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ef7ac68..6557f66 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8837,6 +8837,17 @@ very large effectively disables garbage collection.  
Setting this
 parameter and @option{ggc-min-expand} to zero causes a full collection
 to occur at every opportunity.
 
+@item ggc-free-threshold
+
+Only free memory back to the system when it would free more than this
+many percent of the total allocated memory. Default is 20 percent.
+This avoids memory fragmentation.
+
+@item ggc-free-min
+
+Only free memory back to the system when it would free more than this.
+Unit is kilobytes. 
+
 @item max-reload-search-insns
 The maximum number of instruction reload should look backward for equivalent
 register.  Increasing values mean more aggressive optimization, making the
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 6e08cda..cd1c41a 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1968,14 +1968,19 @@ ggc_collect (void)
   if (GGC_DEBUG_LEVEL >= 2)
     fprintf (G.debug_file, "BEGIN COLLECTING\n");
 
+  /* Release the pages we freed the last time we collected, but didn't
+     reuse in the interim.  But only do this if this would free a 
+     reasonable number of pages. Otherwise hold on to them
+     to avoid virtual memory fragmentation. */
+  if (G.bytes_mapped - G.allocated >= 
+       (PARAM_VALUE (GGC_FREE_THRESHOLD) / 100.0) * G.bytes_mapped &&
+      G.bytes_mapped - G.allocated >= (size_t)PARAM_VALUE (GGC_FREE_MIN) * 
1024)
+    release_pages ();
+
   /* Zero the total allocated bytes.  This will be recalculated in the
      sweep phase.  */
   G.allocated = 0;
 
-  /* Release the pages we freed the last time we collected, but didn't
-     reuse in the interim.  */
-  release_pages ();
-
   /* Indicate that we've seen collections at this context depth.  */
   G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 
1;
 
diff --git a/gcc/params.def b/gcc/params.def
index 5e49c48..ca28715 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -561,6 +561,16 @@ DEFPARAM(GGC_MIN_HEAPSIZE,
 #undef GGC_MIN_EXPAND_DEFAULT
 #undef GGC_MIN_HEAPSIZE_DEFAULT
 
+DEFPARAM(GGC_FREE_THRESHOLD,
+       "ggc-free-threshold",
+       "Dont free memory back to system less this percent of the total memory",
+       20, 0, 100)
+
+DEFPARAM(GGC_FREE_MIN,
+        "ggc-free-min",
+        "Dont free less memory than this back to the system, in kilobytes",
+        8 * 1024, 0, 0)
+
 DEFPARAM(PARAM_MAX_RELOAD_SEARCH_INSNS,
         "max-reload-search-insns",
         "The maximum number of instructions to search backward when looking 
for equivalent reload",
-- 
1.7.5.4

Reply via email to