*/
#define DEFAULT_REMSET_SIZE 1024
+
+/*
+ * Minimum allowance for nursery allocations, as a multiple of the size of nursery.
+ *
+ * We allow at least this much allocation to happen to the major heap from multiple
+ * minor collections before triggering a major collection.
+ *
+ * Bigger values increases throughput by allowing more garbage to sit in the major heap.
+ * Smaller values leads to better memory effiency but more frequent major collections.
+ */
+#define SGEN_MIN_ALLOWANCE_NURSERY_SIZE_RATIO 4
+
#endif
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-archdep.h"
#include "metadata/sgen-bridge.h"
+#include "metadata/sgen-memory-governor.h"
#include "metadata/mono-gc.h"
#include "metadata/method-builder.h"
#include "metadata/profiler-private.h"
static gboolean use_cardtable;
-#define MIN_MINOR_COLLECTION_ALLOWANCE (DEFAULT_NURSERY_SIZE * 4)
-
#define SCAN_START_SIZE SGEN_SCAN_START_SIZE
static mword pagesize = 4096;
MonoNativeThreadId main_gc_thread = NULL;
#endif
-/*
- * ######################################################################
- * ######## Heap size accounting
- * ######################################################################
- */
-/*heap limits*/
-static mword max_heap_size = ((mword)0)- ((mword)1);
-static mword soft_heap_limit = ((mword)0) - ((mword)1);
-static mword allocated_heap;
-
/*Object was pinned during the current collection*/
static mword objects_pinned;
-void
-sgen_release_space (mword size, int space)
-{
- allocated_heap -= size;
-}
-
-static size_t
-available_free_space (void)
-{
- return max_heap_size - MIN (allocated_heap, max_heap_size);
-}
-
-gboolean
-sgen_try_alloc_space (mword size, int space)
-{
- if (available_free_space () < size)
- return FALSE;
-
- allocated_heap += size;
- mono_runtime_resource_check_limit (MONO_RESOURCE_GC_HEAP, allocated_heap);
- return TRUE;
-}
-
-static void
-init_heap_size_limits (glong max_heap, glong soft_limit)
-{
- if (soft_limit)
- soft_heap_limit = soft_limit;
-
- if (max_heap == 0)
- return;
-
- if (max_heap < soft_limit) {
- fprintf (stderr, "max-heap-size must be at least as large as soft-heap-limit.\n");
- exit (1);
- }
-
- if (max_heap < sgen_nursery_size * 4) {
- fprintf (stderr, "max-heap-size must be at least 4 times larger than nursery size.\n");
- exit (1);
- }
- max_heap_size = max_heap - sgen_nursery_size;
-}
-
/*
* ######################################################################
* ######## Macros and function declarations.
if (!*major_collector.have_swept) {
if (overwrite)
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+ minor_collection_allowance = sgen_memgov_min_allowance ();
return;
}
*/
allowance_target = (mword)((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));
- 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 (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), sgen_memgov_min_allowance ());
- if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
- if (new_heap_size > soft_heap_limit)
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
- else
- minor_collection_allowance = MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
- }
+ minor_collection_allowance = sgen_memgov_adjust_allowance (minor_collection_allowance, new_heap_size);
if (debug_print_allowance) {
mword old_major = last_collection_old_num_major_sections * major_collector.section_size;
need_major_collection (mword space_needed)
{
mword los_alloced = los_memory_usage - MIN (last_collection_los_memory_usage, los_memory_usage);
- return (space_needed > available_free_space ()) ||
+ return (space_needed > sgen_memgov_available_free_space ()) ||
minor_collection_sections_alloced * major_collector.section_size + los_alloced > minor_collection_allowance;
}
conservative_stack_mark = TRUE;
sgen_nursery_size = DEFAULT_NURSERY_SIZE;
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+ minor_collection_allowance = sgen_memgov_min_allowance ();
if (opts) {
for (ptr = opts; *ptr; ++ptr) {
if (minor_collector_opt)
g_free (minor_collector_opt);
- init_heap_size_limits (max_heap, soft_limit);
+ sgen_memgov_init (max_heap, soft_limit);
alloc_nursery ();
SPACE_LOS
};
-gboolean sgen_try_alloc_space (mword size, int space) MONO_INTERNAL;
-void sgen_release_space (mword size, int space) MONO_INTERNAL;
void sgen_pin_object (void *object, SgenGrayQueue *queue) MONO_INTERNAL;
void sgen_parallel_pin_or_update (void **ptr, void *obj, MonoVTable *vt, SgenGrayQueue *queue) MONO_INTERNAL;
void sgen_collect_major_no_lock (const char *reason) MONO_INTERNAL;
#include "metadata/sgen-gc.h"
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-cardtable.h"
+#include "metadata/sgen-memory-governor.h"
#include "utils/mono-mmap.h"
#define LOS_SECTION_SIZE (1024 * 1024)
if (free_chunks)
return (LOSObject*)free_chunks;
- if (!sgen_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
+ if (!sgen_memgov_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
return NULL;
section = sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE);
size += pagesize - 1;
size &= ~(pagesize - 1);
sgen_free_os_memory (obj, size);
- sgen_release_space (size, SPACE_LOS);
+ sgen_memgov_release_space (size, SPACE_LOS);
} else {
free_los_section_memory (obj, size + sizeof (LOSObject));
#ifdef LOS_CONSISTENCY_CHECKS
alloc_size += sizeof (LOSObject);
alloc_size += pagesize - 1;
alloc_size &= ~(pagesize - 1);
- if (sgen_try_alloc_space (alloc_size, SPACE_LOS)) {
+ if (sgen_memgov_try_alloc_space (alloc_size, SPACE_LOS)) {
obj = sgen_alloc_os_memory (alloc_size, TRUE);
if (obj)
obj->huge_object = TRUE;
else
los_sections = next;
sgen_free_os_memory (section, LOS_SECTION_SIZE);
- sgen_release_space (LOS_SECTION_SIZE, SPACE_LOS);
+ sgen_memgov_release_space (LOS_SECTION_SIZE, SPACE_LOS);
section = next;
--los_num_sections;
continue;
#include "metadata/sgen-gc.h"
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-cardtable.h"
+#include "metadata/sgen-memory-governor.h"
#include "metadata/gc-internal.h"
#define MS_BLOCK_SIZE (16*1024)
empty_blocks = block;
block->used = FALSE;
block->zeroed = FALSE;
- sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+ sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
}
#else
static void*
{
void *empty;
- sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+ sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
memset (block, 0, MS_BLOCK_SIZE);
do {
char *obj_start;
int i;
- if (!sgen_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
+ if (!sgen_memgov_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
return FALSE;
#ifdef FIXED_HEAP
#include "metadata/sgen-gc.h"
#include "metadata/sgen-memory-governor.h"
+#include "utils/mono-counters.h"
+
+#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(DEFAULT_NURSERY_SIZE * SGEN_MIN_ALLOWANCE_NURSERY_SIZE_RATIO))
+
+/*heap limits*/
+static mword max_heap_size = ((mword)0)- ((mword)1);
+static mword soft_heap_limit = ((mword)0) - ((mword)1);
+static mword allocated_heap;
+
+
+mword
+sgen_memgov_available_free_space (void)
+{
+ return max_heap_size - MIN (allocated_heap, max_heap_size);
+}
+
+mword
+sgen_memgov_min_allowance (void)
+{
+ return MIN_MINOR_COLLECTION_ALLOWANCE;
+}
+
+mword
+sgen_memgov_adjust_allowance (mword allowance_estimate, mword new_heap_size)
+{
+ if (new_heap_size + allowance_estimate > soft_heap_limit) {
+ if (new_heap_size > soft_heap_limit)
+ return MIN_MINOR_COLLECTION_ALLOWANCE;
+ else
+ return MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
+ }
+ return allowance_estimate;
+}
+
+void
+sgen_memgov_release_space (mword size, int space)
+{
+ allocated_heap -= size;
+}
+
+gboolean
+sgen_memgov_try_alloc_space (mword size, int space)
+{
+ if (sgen_memgov_available_free_space () < size)
+ return FALSE;
+
+ allocated_heap += size;
+ mono_runtime_resource_check_limit (MONO_RESOURCE_GC_HEAP, allocated_heap);
+ return TRUE;
+}
+
+void
+sgen_memgov_init (glong max_heap, glong soft_limit)
+{
+ if (soft_limit)
+ soft_heap_limit = soft_limit;
+
+ if (max_heap == 0)
+ return;
+
+ if (max_heap < soft_limit) {
+ fprintf (stderr, "max-heap-size must be at least as large as soft-heap-limit.\n");
+ exit (1);
+ }
+
+ if (max_heap < sgen_nursery_size * 4) {
+ fprintf (stderr, "max-heap-size must be at least 4 times larger than nursery size.\n");
+ exit (1);
+ }
+ max_heap_size = max_heap - sgen_nursery_size;
+}
#endif
#ifndef __MONO_SGEN_MEMORY_GOVERNOR_H__
#define __MONO_SGEN_MEMORY_GOVERNOR_H__
+void sgen_memgov_init (glong max_heap, glong soft_limit) MONO_INTERNAL;
+void sgen_memgov_release_space (mword size, int space) MONO_INTERNAL;
+gboolean sgen_memgov_try_alloc_space (mword size, int space) MONO_INTERNAL;
+mword sgen_memgov_adjust_allowance (mword allowance_estimate, mword new_heap_size) MONO_INTERNAL;
+mword sgen_memgov_min_allowance (void) MONO_INTERNAL;
+mword sgen_memgov_available_free_space (void) MONO_INTERNAL;
#endif