Merge pull request #2573 from BrzVlad/fix-conc-memusage
authorMark Probst <mark.probst@gmail.com>
Fri, 12 Feb 2016 21:09:38 +0000 (15:09 -0600)
committerMark Probst <mark.probst@gmail.com>
Fri, 12 Feb 2016 21:09:38 +0000 (15:09 -0600)
[sgen] Improve memory usage with the concurrent collector

mono/sgen/sgen-conf.h
mono/sgen/sgen-gc.c
mono/sgen/sgen-memory-governor.c
mono/sgen/sgen-memory-governor.h

index 5a0e871e22fecc779083f53fea42bc4945f6849a..11a8998478e765e8083e337c57a9f48c6fb7a9ee 100644 (file)
@@ -190,12 +190,6 @@ typedef mword SgenDescriptor;
  */
 #define SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO 0.33
 
-/*
- * How much more we allow the heap to grow, relative to the allowance, while doing
- * a concurrent collection, before forcing its finish.
- */
-#define SGEN_DEFAULT_CONCURRENT_HEAP_ALLOWANCE_RATIO 0.25
-
 /*
  * Default ratio of memory we want to release in a major collection in relation to the the current heap size.
  *
index 34da3f15ab339c4b84d83585d4d265832fdc1c24..ae368d6d6d2225b140948d64dabfbfcdb532423a 100644 (file)
@@ -1974,6 +1974,7 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean
        time_major_fragment_creation += TV_ELAPSED (atv, btv);
 
        binary_protocol_sweep_begin (GENERATION_OLD, !major_collector.sweeps_lazily);
+       sgen_memgov_major_pre_sweep ();
 
        TV_GETTIME (atv);
        time_major_free_bigobjs += TV_ELAPSED (btv, atv);
index ce34f7f4a67a7d304ff038e674c01aa38651e0c5..611ae5c118f4d66b7e1eb982fd4d32048e78a20b 100644 (file)
@@ -56,6 +56,9 @@ static gboolean debug_print_allowance = FALSE;
 /* use this to tune when to do a major/minor collection */
 static mword major_collection_trigger_size;
 
+static mword major_pre_sweep_heap_size;
+static mword major_start_heap_size;
+
 static mword last_major_num_sections = 0;
 static mword last_los_memory_usage = 0;
 
@@ -73,6 +76,7 @@ static void
 sgen_memgov_calculate_minor_collection_allowance (void)
 {
        size_t new_major, new_heap_size, allowance_target, allowance;
+       size_t decrease;
 
        if (!need_calculate_minor_collection_allowance)
                return;
@@ -90,6 +94,16 @@ sgen_memgov_calculate_minor_collection_allowance (void)
 
        allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
 
+       /*
+        * For the concurrent collector, we decrease the allowance relative to the memory
+        * growth during the M&S phase, survival rate of the collection and the allowance
+        * ratio.
+        */
+       decrease = (major_pre_sweep_heap_size - major_start_heap_size) * ((float)new_heap_size / major_pre_sweep_heap_size) * (SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO + 1);
+       if (decrease > allowance)
+               decrease = allowance;
+       allowance -= decrease;
+
        if (new_heap_size + allowance > soft_heap_limit) {
                if (new_heap_size > soft_heap_limit)
                        allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
@@ -129,13 +143,14 @@ sgen_need_major_collection (mword space_needed)
                if (heap_size <= major_collection_trigger_size)
                        return FALSE; 
 
-               /* We allow the heap to grow an additional third of the allowance during a concurrent collection */
-               if ((heap_size - major_collection_trigger_size) >
-                               (major_collection_trigger_size
-                               * (SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO / (SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO + 1))
-                               * SGEN_DEFAULT_CONCURRENT_HEAP_ALLOWANCE_RATIO)) {
+               /*
+                * The more the heap grows, the more we need to decrease the allowance above,
+                * in order to have similar trigger sizes as the synchronous collector.
+                * If the heap grows so much that we would need to have a negative allowance,
+                * we force the finishing of the collection, to avoid increased memory usage.
+                */
+               if ((heap_size - major_start_heap_size) > major_start_heap_size * SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO)
                        return TRUE;
-               }
                return FALSE;
        }
 
@@ -163,13 +178,25 @@ sgen_memgov_minor_collection_end (void)
 {
 }
 
+void
+sgen_memgov_major_pre_sweep (void)
+{
+       if (sgen_concurrent_collection_in_progress ()) {
+               major_pre_sweep_heap_size = get_heap_size ();
+       } else {
+               /* We decrease the allowance only in the concurrent case */
+               major_pre_sweep_heap_size = major_start_heap_size;
+       }
+}
+
 void
 sgen_memgov_major_collection_start (void)
 {
        need_calculate_minor_collection_allowance = TRUE;
+       major_start_heap_size = get_heap_size ();
 
        if (debug_print_allowance) {
-               SGEN_LOG (0, "Starting collection with heap size %ld bytes", (long)get_heap_size ());
+               SGEN_LOG (0, "Starting collection with heap size %ld bytes", (long)major_start_heap_size);
        }
 }
 
index 0115ec6e0605e2755c4b28dc8c020b89f8ea9466..669b59734e99200ffadae2dc540a7b8137f6349c 100644 (file)
@@ -33,6 +33,7 @@ gboolean sgen_memgov_try_alloc_space (mword size, int space);
 void sgen_memgov_minor_collection_start (void);
 void sgen_memgov_minor_collection_end (void);
 
+void sgen_memgov_major_pre_sweep (void);
 void sgen_memgov_major_collection_start (void);
 void sgen_memgov_major_collection_end (gboolean forced);