[sgen] Resize nursery according also to pause times
authorVlad Brezae <brezaevlad@gmail.com>
Fri, 7 Apr 2017 23:21:48 +0000 (02:21 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Mon, 15 May 2017 09:52:51 +0000 (12:52 +0300)
mono/sgen/sgen-conf.h
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-nursery-allocator.c

index 324009cc2951b2fc482d09f79122907bf41193bd..63e922c470e0745f5e16340a858be806b08deb2b 100644 (file)
@@ -211,4 +211,12 @@ typedef mword SgenDescriptor;
 #define SGEN_DEFAULT_NURSERY_SIZE      (1 << 22)
 #define SGEN_DEFAULT_NURSERY_MAX_SIZE  (1 << 25)
 
+/*
+ * We are trying to keep pauses lower than this (ms). We use it for dynamic nursery
+ * sizing heuristics. We are keeping leeway in order to be prepared for work-load
+ * variations.
+ */
+#define SGEN_MAX_PAUSE_TIME 30
+#define SGEN_MAX_PAUSE_MARGIN 0.66f
+
 #endif
index 9f8a8aa63ffe9aa0c9e8af0cd8d54940a8e3dbe6..2c0337d6a35e25bd1e8964abda78e745fd4d795c 100644 (file)
@@ -288,6 +288,9 @@ static guint64 time_major_fragment_creation = 0;
 
 static guint64 time_max = 0;
 
+static int sgen_max_pause_time = SGEN_MAX_PAUSE_TIME;
+static float sgen_max_pause_margin = SGEN_MAX_PAUSE_MARGIN;
+
 static SGEN_TV_DECLARE (time_major_conc_collection_start);
 static SGEN_TV_DECLARE (time_major_conc_collection_end);
 
@@ -1612,6 +1615,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
        SgenGrayQueue gc_thread_gray_queue;
        SgenObjectOperations *object_ops_nopar, *object_ops_par = NULL;
        ScanCopyContext ctx;
+       int duration;
        TV_DECLARE (atv);
        TV_DECLARE (btv);
        SGEN_TV_DECLARE (last_minor_collection_start_tv);
@@ -1743,7 +1747,13 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
        if (remset_consistency_checks)
                sgen_check_remset_consistency ();
 
-       sgen_resize_nursery ();
+
+       TV_GETTIME (btv);
+       duration = (int)(TV_ELAPSED (last_minor_collection_start_tv, btv) / 10000);
+       if (duration > (sgen_max_pause_time * sgen_max_pause_margin))
+               sgen_resize_nursery (TRUE);
+       else
+               sgen_resize_nursery (FALSE);
 
        /* walk the pin_queue, build up the fragment list of free memory, unmark
         * pinned objects as we go, memzero() the empty fragments so they are ready for the
index 1a727a6d3338b8efcd4fa89a36b2b1a179a74e35..27727a537b697e8bd8bebe08166d8ee320d7e439 100644 (file)
@@ -897,7 +897,7 @@ void sgen_los_mark_mod_union_card (GCObject *mono_obj, void **ptr);
 void sgen_clear_nursery_fragments (void);
 void sgen_nursery_allocator_prepare_for_pinning (void);
 void sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, size_t min_size, size_t max_size);
-void sgen_resize_nursery (void);
+void sgen_resize_nursery (gboolean need_shrink);
 mword sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue);
 void sgen_init_nursery_allocator (void);
 void sgen_nursery_allocator_init_heavy_stats (void);
index 1452b6b7d79b5e995472a55cc1e1a179b9ec525d..53a7999a74e88ff75f06565f4c59fb3134f510b6 100644 (file)
@@ -920,7 +920,7 @@ sgen_nursery_allocator_set_nursery_bounds (char *start, size_t min_size, size_t
 }
 
 void
-sgen_resize_nursery (void)
+sgen_resize_nursery (gboolean need_shrink)
 {
        size_t major_size;
 
@@ -938,11 +938,11 @@ sgen_resize_nursery (void)
         * section).
         */
        if ((sgen_nursery_size * 2) < (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) &&
-                       (sgen_nursery_size * 2) <= sgen_nursery_max_size) {
+                       (sgen_nursery_size * 2) <= sgen_nursery_max_size && !need_shrink) {
                if ((nursery_section->end_data - nursery_section->data) == sgen_nursery_size)
                        nursery_section->end_data += sgen_nursery_size;
                sgen_nursery_size *= 2;
-       } else if (sgen_nursery_size > (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) &&
+       } else if ((sgen_nursery_size > (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) || need_shrink) &&
                        (sgen_nursery_size / 2) >= sgen_nursery_min_size) {
                sgen_nursery_size /= 2;
        }