Permalink
Browse files

[sgen] Option for an allowance limit.

The metric for deciding when to trigger a major collection assumes
that there's unlimited memory, so it does, especially since it's
probably buggy and certainly not very smart, sometimes allow too much
allocation to happen.  This new option is a way to tell SGen where to
draw the line.  Note that memory will still be allocated, it's just
that once the limit is overstepped, major collections happen more
frequently to keep memory usage down.
  • Loading branch information...
1 parent 044e88a commit 3e50ef333b20ab20ecec0379425e2818ef0515f8 @schani schani committed Jul 13, 2011
Showing with 50 additions and 6 deletions.
  1. +5 −0 man/mono.1
  2. +45 −6 mono/metadata/sgen-gc.c
View
@@ -1034,6 +1034,11 @@ for the fixed-heap Mark&Sweep collector (i.e. `marksweep-fixed' and
`k', `m' and `g' to specify kilo-, mega- and gigabytes, respectively.
The default is 512 megabytes.
.TP
+\fBsoft-heap-limit=\fIsize\fR
+Once the heap size gets larger than this size, ignore what the default
+major collection trigger metric says and only allow four nursery size's
+of major heap growth between major collections.
+.TP
\fBwbarrier=\fIwbarrier\fR
Specifies which write barrier to use. Options are `cardtable' and
`remset'. The card table barrier is faster but less precise, and only
View
@@ -719,6 +719,7 @@ pthread_t main_gc_thread = NULL;
*/
/*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*/
@@ -747,11 +748,19 @@ mono_sgen_try_alloc_space (mword size, int space)
}
static void
-init_heap_size_limits (glong max_heap)
+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 < nursery_size * 4) {
fprintf (stderr, "max-heap-size must be at least 4 times larger than nursery size.\n");
exit (1);
@@ -2796,7 +2805,7 @@ static void
try_calculate_minor_collection_allowance (gboolean overwrite)
{
int num_major_sections, num_major_sections_saved, save_target, allowance_target;
- mword los_memory_saved;
+ mword los_memory_saved, new_major, new_heap_size;
if (overwrite)
g_assert (need_calculate_minor_collection_allowance);
@@ -2815,7 +2824,16 @@ try_calculate_minor_collection_allowance (gboolean overwrite)
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);
- save_target = ((num_major_sections * major_collector.section_size) + los_memory_saved) / 2;
+ new_major = num_major_sections * major_collector.section_size;
+ new_heap_size = new_major + last_collection_los_memory_usage;
+
+ /*
+ * FIXME: Why is save_target half the major memory plus half the
+ * LOS memory saved? Shouldn't it be half the major memory
+ * saved plus half the LOS memory saved? Or half the whole heap
+ * size?
+ */
+ save_target = (new_major + los_memory_saved) / 2;
/*
* We aim to allow the allocation of as many sections as is
@@ -2836,14 +2854,20 @@ try_calculate_minor_collection_allowance (gboolean overwrite)
minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_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);
+ }
+
if (debug_print_allowance) {
mword old_major = last_collection_old_num_major_sections * major_collector.section_size;
- mword new_major = num_major_sections * major_collector.section_size;
fprintf (gc_debug_file, "Before collection: %ld bytes (%ld major, %ld LOS)\n",
old_major + last_collection_old_los_memory_usage, old_major, last_collection_old_los_memory_usage);
fprintf (gc_debug_file, "After collection: %ld bytes (%ld major, %ld LOS)\n",
- new_major + last_collection_los_memory_usage, new_major, last_collection_los_memory_usage);
+ new_heap_size, new_major, last_collection_los_memory_usage);
fprintf (gc_debug_file, "Allowance: %ld bytes\n", minor_collection_allowance);
}
@@ -6619,6 +6643,7 @@ mono_gc_base_init (void)
char *major_collector_opt = NULL;
struct sigaction sinfo;
glong max_heap = 0;
+ glong soft_limit = 0;
int num_workers;
int result;
@@ -6776,6 +6801,19 @@ mono_gc_base_init (void)
}
continue;
}
+ if (g_str_has_prefix (opt, "soft-heap-limit=")) {
+ opt = strchr (opt, '=') + 1;
+ if (*opt && mono_gc_parse_environment_string_extract_number (opt, &soft_limit)) {
+ if (soft_limit <= 0) {
+ fprintf (stderr, "soft-heap-limit must be positive.\n");
+ exit (1);
+ }
+ } else {
+ fprintf (stderr, "soft-heap-limit must be an integer.\n");
+ exit (1);
+ }
+ continue;
+ }
if (g_str_has_prefix (opt, "workers=")) {
long val;
char *endptr;
@@ -6834,6 +6872,7 @@ mono_gc_base_init (void)
if (!(major_collector.handle_gc_param && major_collector.handle_gc_param (opt))) {
fprintf (stderr, "MONO_GC_PARAMS must be a comma-delimited list of one or more of the following:\n");
fprintf (stderr, " max-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\n");
+ fprintf (stderr, " soft-heap-limit=n (where N is an integer, possibly with a k, m or a g suffix)\n");
fprintf (stderr, " nursery-size=N (where N is an integer, possibly with a k, m or a g suffix)\n");
fprintf (stderr, " major=COLLECTOR (where COLLECTOR is `marksweep', `marksweep-par' or `copying')\n");
fprintf (stderr, " wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n");
@@ -6854,7 +6893,7 @@ mono_gc_base_init (void)
nursery_size = DEFAULT_NURSERY_SIZE;
minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
- init_heap_size_limits (max_heap);
+ init_heap_size_limits (max_heap, soft_limit);
alloc_nursery ();

0 comments on commit 3e50ef3

Please sign in to comment.