[sgen] Finish concurrent collection if the heap grows too much
authorVlad Brezae <brezaevlad@gmail.com>
Wed, 28 Oct 2015 20:29:11 +0000 (22:29 +0200)
committerVlad Brezae <brezaevlad@gmail.com>
Tue, 3 Nov 2015 00:07:28 +0000 (02:07 +0200)
In order to achieve this, when asked to do a major collection, we finish the concurrent collection immediately, regardless if we are explicitely requested or not to wait_to_finish.

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

index 11a8998478e765e8083e337c57a9f48c6fb7a9ee..5a0e871e22fecc779083f53fea42bc4945f6849a 100644 (file)
@@ -190,6 +190,12 @@ 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 9a8d10806dac72c5f9f4bc06d4570a09cd97f68d..6dd730dcbe9857f2743d74ec6b3bab704f93e668 100644 (file)
@@ -2182,7 +2182,7 @@ sgen_ensure_free_space (size_t size)
                                generation_to_collect = GENERATION_OLD;
                        }
                } else if (sgen_need_major_collection (size)) {
-                       reason = "Minor allowance";
+                       reason = concurrent_collection_in_progress ? "Forced finish concurrent collection" : "Minor allowance";
                        generation_to_collect = GENERATION_OLD;
                } else {
                        generation_to_collect = GENERATION_NURSERY;
@@ -2229,18 +2229,18 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
 
        if (concurrent_collection_in_progress) {
                /*
-                * We update the concurrent collection.  If it finished, we're done.  If
-                * not, and we've been asked to do a nursery collection, we do that.
+                * If the concurrent worker is finished or we are asked to do a major collection
+                * then we finish the concurrent collection.
                 */
-               gboolean finish = major_should_finish_concurrent_collection () || (wait_to_finish && generation_to_collect == GENERATION_OLD);
+               gboolean finish = major_should_finish_concurrent_collection () || generation_to_collect == GENERATION_OLD;
 
                if (finish) {
                        major_finish_concurrent_collection (wait_to_finish);
                        oldest_generation_collected = GENERATION_OLD;
                } else {
+                       SGEN_ASSERT (0, generation_to_collect == GENERATION_NURSERY, "Why aren't we finishing the concurrent collection?");
                        major_update_concurrent_collection ();
-                       if (generation_to_collect == GENERATION_NURSERY)
-                               collect_nursery (NULL, FALSE);
+                       collect_nursery (NULL, FALSE);
                }
 
                goto done;
index 824d2f7183c5e17cd37cc1a83745685e36792556..ce34f7f4a67a7d304ff038e674c01aa38651e0c5 100644 (file)
@@ -112,13 +112,32 @@ sgen_memgov_calculate_minor_collection_allowance (void)
        }
 }
 
+static inline size_t
+get_heap_size (void)
+{
+       return major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
+}
+
 gboolean
 sgen_need_major_collection (mword space_needed)
 {
        size_t heap_size;
 
-       if (sgen_concurrent_collection_in_progress ())
+       if (sgen_concurrent_collection_in_progress ()) {
+               heap_size = get_heap_size ();
+
+               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)) {
+                       return TRUE;
+               }
                return FALSE;
+       }
 
        /* FIXME: This is a cop-out.  We should have some way of figuring this out. */
        if (!major_collector.have_swept ())
@@ -129,7 +148,7 @@ sgen_need_major_collection (mword space_needed)
 
        sgen_memgov_calculate_minor_collection_allowance ();
 
-       heap_size = major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
+       heap_size = get_heap_size ();
 
        return heap_size > major_collection_trigger_size;
 }
@@ -150,7 +169,7 @@ sgen_memgov_major_collection_start (void)
        need_calculate_minor_collection_allowance = TRUE;
 
        if (debug_print_allowance) {
-               SGEN_LOG (0, "Starting collection with heap size %ld bytes", (long)(major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage));
+               SGEN_LOG (0, "Starting collection with heap size %ld bytes", (long)get_heap_size ());
        }
 }