[sgen] Rename `have_computed_minor_collection_allowance` to `free_swept_blocks`.
[mono.git] / mono / metadata / sgen-memory-governor.c
index 448ebef3f05ff0df0ebabe70767c76c197de9a30..63b01840674b0f1136a648715cfad9fd98b9ab71 100644 (file)
@@ -48,6 +48,7 @@ static double save_target_ratio = SGEN_DEFAULT_SAVE_TARGET_RATIO;
 /**/
 static mword allocated_heap;
 static mword total_alloc = 0;
+static mword total_alloc_max = 0;
 
 /* GC triggers. */
 
@@ -72,21 +73,13 @@ static mword last_collection_los_memory_alloced;
 static mword sgen_memgov_available_free_space (void);
 
 
-static mword
-double_to_mword_with_saturation (double value)
-{
-       if (value >= (double)MWORD_MAX_VALUE)
-               return MWORD_MAX_VALUE;
-       return (mword)value;
-}
-
 /* GC trigger heuristics. */
 
 static void
 sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
 {
-       size_t num_major_sections, num_major_sections_saved;
-       mword los_memory_saved, new_major, new_heap_size, save_target, allowance_target;
+       size_t num_major_sections;
+       mword new_major, new_heap_size, allowance_target;
 
        if (overwrite)
                g_assert (need_calculate_minor_collection_allowance);
@@ -94,7 +87,7 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
        if (!need_calculate_minor_collection_allowance)
                return;
 
-       if (!*major_collector.have_swept) {
+       if (!major_collector.have_finished_sweeping ()) {
                if (overwrite)
                        minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
                return;
@@ -102,32 +95,16 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
 
        num_major_sections = major_collector.get_num_major_sections ();
 
-       num_major_sections_saved = MAX (last_collection_old_num_major_sections - num_major_sections, 0);
-       los_memory_saved = MAX (last_collection_old_los_memory_usage - last_collection_los_memory_usage, 1);
-
        new_major = num_major_sections * major_collector.section_size;
        new_heap_size = new_major + last_collection_los_memory_usage;
 
-       save_target = (mword)((new_major + last_collection_los_memory_usage) * SGEN_DEFAULT_SAVE_TARGET_RATIO);
-
        /*
-        * We aim to allow the allocation of as many sections as is
-        * necessary to reclaim save_target sections in the next
-        * collection.  We assume the collection pattern won't change.
-        * In the last cycle, we had num_major_sections_saved for
-        * minor_collection_sections_alloced.  Assuming things won't
-        * change, this must be the same ratio as save_target for
-        * allowance_target, i.e.
-        *
-        *    num_major_sections_saved            save_target
-        * --------------------------------- == ----------------
-        * minor_collection_sections_alloced    allowance_target
-        *
-        * hence:
+        * We allow the heap to grow by one third its current size before we start the next
+        * major collection.
         */
-       allowance_target = double_to_mword_with_saturation ((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved));
+       allowance_target = new_heap_size / 3;
 
-       minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_ALLOWANCE);
+       minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
 
        if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
                if (new_heap_size > soft_heap_limit)
@@ -146,8 +123,8 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
                SGEN_LOG (1, "Allowance: %ld bytes", (long)minor_collection_allowance);
        }
 
-       if (major_collector.have_computed_minor_collection_allowance)
-               major_collector.have_computed_minor_collection_allowance ();
+       if (major_collector.free_swept_blocks)
+               major_collector.free_swept_blocks ();
 
        need_calculate_minor_collection_allowance = FALSE;
 }
@@ -311,6 +288,7 @@ sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_desc
                SGEN_ATOMIC_ADD_P (total_alloc, size);
                if (flags & SGEN_ALLOC_HEAP)
                        MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+               total_alloc_max = MAX (total_alloc_max, total_alloc);
        }
        return ptr;
 }
@@ -329,6 +307,7 @@ sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags
                SGEN_ATOMIC_ADD_P (total_alloc, size);
                if (flags & SGEN_ALLOC_HEAP)
                        MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+               total_alloc_max = MAX (total_alloc_max, total_alloc);
        }
        return ptr;
 }
@@ -345,6 +324,7 @@ sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags)
        SGEN_ATOMIC_ADD_P (total_alloc, -(gssize)size);
        if (flags & SGEN_ALLOC_HEAP)
                MONO_GC_HEAP_FREE ((mword)addr, size);
+       total_alloc_max = MAX (total_alloc_max, total_alloc);
 }
 
 int64_t
@@ -375,8 +355,10 @@ sgen_memgov_release_space (mword size, int space)
 gboolean
 sgen_memgov_try_alloc_space (mword size, int space)
 {
-       if (sgen_memgov_available_free_space () < size)
+       if (sgen_memgov_available_free_space () < size) {
+               SGEN_ASSERT (4, !sgen_is_worker_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
                return FALSE;
+       }
 
        SGEN_ATOMIC_ADD_P (allocated_heap, size);
        mono_runtime_resource_check_limit (MONO_RESOURCE_GC_HEAP, allocated_heap);
@@ -392,6 +374,9 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
        debug_print_allowance = debug_allowance;
        minor_collection_allowance = 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);
+
        if (max_heap == 0)
                return;