[sgen] Simplify allowance logic.
authorMark Probst <mark.probst@gmail.com>
Fri, 6 Feb 2015 01:03:33 +0000 (17:03 -0800)
committerMark Probst <mark.probst@gmail.com>
Thu, 2 Apr 2015 23:41:27 +0000 (16:41 -0700)
Don't use the difference to the last collection, but just calculate the maximum heap
size and trigger a collection when it's reached.

mono/metadata/sgen-gc.h
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-memory-governor.c
mono/metadata/sgen-memory-governor.h

index ef957750be3f0d59f3df40c8170387eac95286ee..40920d9690a3bfcf8fcf1ab0df270fb371533a40 100644 (file)
@@ -704,7 +704,7 @@ struct _SgenMajorCollector {
        gboolean (*obj_is_from_pinned_alloc) (char *obj);
        void (*report_pinned_memory_usage) (void);
        size_t (*get_num_major_sections) (void);
-       size_t (*get_num_major_unswept_old_sections) (void);
+       size_t (*get_bytes_survived_last_sweep) (void);
        gboolean (*handle_gc_param) (const char *opt);
        void (*print_gc_param_usage) (void);
        gboolean (*is_worker_thread) (MonoNativeThreadId thread);
index 718e95fea5c317cf03f90a6ddb9afe120262e33c..a02fd2badfbd5e30368d91109072b70bcb668bd9 100644 (file)
@@ -1787,7 +1787,8 @@ compare_pointers (const void *va, const void *vb) {
 static void
 major_free_swept_blocks (void)
 {
-       size_t section_reserve = sgen_get_minor_collection_allowance () / MS_BLOCK_SIZE;
+       /* FIXME: use something sensible here. */
+       size_t section_reserve = DEFAULT_NURSERY_SIZE * 2 / MS_BLOCK_SIZE;
 
        SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks");
 
@@ -1983,6 +1984,7 @@ major_get_used_size (void)
        return size;
 }
 
+/* FIXME: return number of bytes, not of sections */
 static size_t
 get_num_major_sections (void)
 {
@@ -1990,14 +1992,15 @@ get_num_major_sections (void)
 }
 
 /*
- * Returns the number of major sections that were present when the last sweep was initiated,
- * and were not freed during the sweep.  They are the basis for calculating the allowance.
+ * Returns the number of bytes in blocks that were present when the last sweep was
+ * initiated, and were not freed during the sweep.  They are the basis for calculating the
+ * allowance.
  */
 static size_t
-get_num_major_unswept_old_sections (void)
+get_bytes_survived_last_sweep (void)
 {
        SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Can only query unswept sections after sweep");
-       return num_major_sections_before_sweep - num_major_sections_freed_in_sweep;
+       return (num_major_sections_before_sweep - num_major_sections_freed_in_sweep) * MS_BLOCK_SIZE;
 }
 
 static gboolean
@@ -2466,7 +2469,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        collector->obj_is_from_pinned_alloc = obj_is_from_pinned_alloc;
        collector->report_pinned_memory_usage = major_report_pinned_memory_usage;
        collector->get_num_major_sections = get_num_major_sections;
-       collector->get_num_major_unswept_old_sections = get_num_major_unswept_old_sections;
+       collector->get_bytes_survived_last_sweep = get_bytes_survived_last_sweep;
        collector->handle_gc_param = major_handle_gc_param;
        collector->print_gc_param_usage = major_print_gc_param_usage;
        collector->post_param_init = post_param_init;
index aa9470f97c48c45862a17b3603dfbbf988d455b9..bf8831268e4b958d13a573b0cbba41bd7c0c2733 100644 (file)
@@ -57,17 +57,15 @@ static gboolean debug_print_allowance = FALSE;
 
 /* use this to tune when to do a major/minor collection */
 static mword memory_pressure = 0;
-static mword minor_collection_allowance;
+static mword major_collection_trigger_size;
 
 static mword last_major_num_sections = 0;
 static mword last_los_memory_usage = 0;
 
 static gboolean need_calculate_minor_collection_allowance;
 
-static mword last_collection_old_num_major_sections;
+/* The size of the LOS after the last major collection, after sweeping. */
 static mword last_collection_los_memory_usage = 0;
-static mword last_collection_old_los_memory_usage;
-static mword last_collection_los_memory_alloced;
 
 static mword sgen_memgov_available_free_space (void);
 
@@ -77,18 +75,14 @@ static mword sgen_memgov_available_free_space (void);
 static void
 sgen_memgov_calculate_minor_collection_allowance (void)
 {
-       size_t num_major_sections;
-       mword new_major, new_heap_size, allowance_target;
+       size_t new_major, new_heap_size, allowance_target, allowance;
 
        if (!need_calculate_minor_collection_allowance)
                return;
 
        SGEN_ASSERT (0, major_collector.have_swept (), "Can only calculate allowance if heap is swept");
 
-       num_major_sections = major_collector.get_num_major_unswept_old_sections ();
-
-       new_major = num_major_sections * major_collector.section_size;
-       /* FIXME: We're using the current major heap size, but the previous LOS size. */
+       new_major = major_collector.get_bytes_survived_last_sweep ();
        new_heap_size = new_major + last_collection_los_memory_usage;
 
        /*
@@ -97,39 +91,34 @@ sgen_memgov_calculate_minor_collection_allowance (void)
         */
        allowance_target = new_heap_size / 3;
 
-       minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
+       allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
 
-       if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
+       if (new_heap_size + allowance > soft_heap_limit) {
                if (new_heap_size > soft_heap_limit)
-                       minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+                       allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
                else
-                       minor_collection_allowance = MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
-       }
-
-       if (debug_print_allowance) {
-               mword old_major = last_collection_old_num_major_sections * major_collector.section_size;
-
-               SGEN_LOG (1, "Before collection: %ld bytes (%ld major, %ld LOS)",
-                                 (long)(old_major + last_collection_old_los_memory_usage), (long)old_major, (long)last_collection_old_los_memory_usage);
-               SGEN_LOG (1, "After collection: %ld bytes (%ld major, %ld LOS)",
-                                 (long)new_heap_size, (long)new_major, (long)last_collection_los_memory_usage);
-               SGEN_LOG (1, "Allowance: %ld bytes", (long)minor_collection_allowance);
+                       allowance = MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
        }
 
+       /* FIXME: Why is this here? */
        if (major_collector.free_swept_blocks)
                major_collector.free_swept_blocks ();
 
+       major_collection_trigger_size = new_heap_size + allowance;
+
        need_calculate_minor_collection_allowance = FALSE;
-}
 
+       if (debug_print_allowance) {
+               SGEN_LOG (0, "Surviving sweep: %ld bytes (%ld major, %ld LOS)", (long)new_heap_size, (long)new_major, (long)last_collection_los_memory_usage);
+               SGEN_LOG (0, "Allowance: %ld bytes", (long)allowance);
+               SGEN_LOG (0, "Trigger size: %ld bytes", (long)major_collection_trigger_size);
+       }
+}
 
 gboolean
 sgen_need_major_collection (mword space_needed)
 {
-       size_t los_alloced;
-       size_t num_sections;
-       size_t num_unswept_old_sections;
-       size_t minor_collection_sections_alloced;
+       size_t heap_size;
 
        if (sgen_concurrent_collection_in_progress ())
                return FALSE;
@@ -138,17 +127,14 @@ sgen_need_major_collection (mword space_needed)
        if (!major_collector.have_swept ())
                return FALSE;
 
-       num_sections = major_collector.get_num_major_sections ();
-       num_unswept_old_sections = major_collector.get_num_major_unswept_old_sections ();
-       SGEN_ASSERT (0, num_sections >= num_unswept_old_sections, "Number of sections should not shrink after sweep");
-       minor_collection_sections_alloced = num_sections - num_unswept_old_sections;
+       if (space_needed > sgen_memgov_available_free_space ())
+               return TRUE;
 
-       if (need_calculate_minor_collection_allowance)
-               sgen_memgov_calculate_minor_collection_allowance ();
+       sgen_memgov_calculate_minor_collection_allowance ();
+
+       heap_size = major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
 
-       los_alloced = los_memory_usage - MIN (last_collection_los_memory_usage, los_memory_usage);
-       return (space_needed > sgen_memgov_available_free_space ()) ||
-               minor_collection_sections_alloced * major_collector.section_size + los_alloced > minor_collection_allowance;
+       return heap_size > major_collection_trigger_size;
 }
 
 void
@@ -164,16 +150,11 @@ sgen_memgov_minor_collection_end (void)
 void
 sgen_memgov_major_collection_start (void)
 {
-       last_collection_old_num_major_sections = sgen_get_major_collector ()->get_num_major_sections ();
-
-       /*
-        * A domain could have been freed, resulting in
-        * los_memory_usage being less than last_collection_los_memory_usage.
-        */
-       last_collection_los_memory_alloced = los_memory_usage - MIN (last_collection_los_memory_usage, los_memory_usage);
-       last_collection_old_los_memory_usage = los_memory_usage;
-
        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));
+       }
 }
 
 void
@@ -187,13 +168,6 @@ sgen_memgov_major_collection_end (gboolean forced)
        }
 }
 
-void
-sgen_memgov_collection_start (int generation)
-{
-       last_major_num_sections = major_collector.get_num_major_sections ();
-       last_los_memory_usage = los_memory_usage;
-}
-
 static void
 log_timming (GGTimingInfo *info)
 {
@@ -225,6 +199,12 @@ log_timming (GGTimingInfo *info)
                        los_memory_usage / 1024);       
 }
 
+/* FIXME: Remove either these or the specialized ones above. */
+void
+sgen_memgov_collection_start (int generation)
+{
+}
+
 void
 sgen_memgov_collection_end (int generation, GGTimingInfo* info, int info_count)
 {
@@ -235,12 +215,6 @@ sgen_memgov_collection_end (int generation, GGTimingInfo* info, int info_count)
        }
 }
 
-mword
-sgen_get_minor_collection_allowance (void)
-{
-       return minor_collection_allowance;
-}
-
 /* Memory pressure API */
 
 /* Negative value to remove */
@@ -377,7 +351,7 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
                soft_heap_limit = soft_limit;
 
        debug_print_allowance = debug_allowance;
-       minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+       major_collection_trigger_size = MIN_MINOR_COLLECTION_ALLOWANCE;
 
        mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc);
        mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max);
@@ -401,7 +375,6 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
 
        if (save_target)
                save_target_ratio = save_target;
-       minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
 }
 
 #endif
index e4629ac5d50549c08c846fa8835b491a68e912ea..0115ec6e0605e2755c4b28dc8c020b89f8ea9466 100644 (file)
@@ -39,7 +39,6 @@ void sgen_memgov_major_collection_end (gboolean forced);
 void sgen_memgov_collection_start (int generation);
 void sgen_memgov_collection_end (int generation, GGTimingInfo* info, int info_count);
 
-mword sgen_get_minor_collection_allowance (void);
 gboolean sgen_need_major_collection (mword space_needed);