rts: Introduce flag to enable the nonmoving old generation
authorBen Gamari <ben@well-typed.com>
Tue, 5 Feb 2019 05:10:43 +0000 (00:10 -0500)
committerBen Gamari <ben@smart-cactus.org>
Fri, 17 May 2019 00:42:44 +0000 (20:42 -0400)
This flag will enable the use of a non-moving oldest generation.

docs/users_guide/runtime_control.rst
includes/rts/Flags.h
rts/RtsFlags.c

index a5c2f14..688543e 100644 (file)
@@ -289,6 +289,24 @@ collection. Hopefully, you won't need any of these in normal operation,
 but there are several things that can be tweaked for maximum
 performance.
 
+.. rts-flag:: -xn
+
+    :default: off
+    :since: 8.8.1
+
+    .. index::
+       single: concurrent mark and sweep
+
+    Enable the concurrent mark-and-sweep garbage collector for old generation
+    collectors. Typically GHC uses a stop-the-world copying garbage collector
+    for all generations. This can cause long pauses in execution during major
+    garbage collections. :rts-flag:`-xn` enables the use of a concurrent
+    mark-and-sweep garbage collector for oldest generation collections.
+    Under this collection strategy oldest-generation garbage collection
+    can proceed concurrently with mutation.
+
+    Note that :rts-flag:`-xn` cannot be used with ``-G1`` nor :rts-flag:`-c`.
+
 .. rts-flag:: -A ⟨size⟩
 
     :default: 1MB
index 63450d5..0558abd 100644 (file)
@@ -52,6 +52,7 @@ typedef struct _GC_FLAGS {
     double  oldGenFactor;
     double  pcFreeHeap;
 
+    bool         useNonmoving;
     uint32_t     generations;
     bool squeezeUpdFrames;
 
@@ -95,6 +96,7 @@ typedef struct _DEBUG_FLAGS {
     bool weak;           /* 'w' */
     bool gccafs;         /* 'G' */
     bool gc;             /* 'g' */
+    bool nonmoving_gc;   /* 'n' */
     bool block_alloc;    /* 'b' */
     bool sanity;         /* 'S'   warning: might be expensive! */
     bool stable;         /* 't' */
index ff9635a..716d8c7 100644 (file)
@@ -153,6 +153,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.GcFlags.heapSizeSuggestionAuto = false;
     RtsFlags.GcFlags.pcFreeHeap         = 3;    /* 3% */
     RtsFlags.GcFlags.oldGenFactor       = 2;
+    RtsFlags.GcFlags.useNonmoving       = false;
     RtsFlags.GcFlags.generations        = 2;
     RtsFlags.GcFlags.squeezeUpdFrames   = true;
     RtsFlags.GcFlags.compact            = false;
@@ -176,6 +177,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.DebugFlags.weak            = false;
     RtsFlags.DebugFlags.gccafs          = false;
     RtsFlags.DebugFlags.gc              = false;
+    RtsFlags.DebugFlags.nonmoving_gc    = false;
     RtsFlags.DebugFlags.block_alloc     = false;
     RtsFlags.DebugFlags.sanity          = false;
     RtsFlags.DebugFlags.stable          = false;
@@ -294,6 +296,7 @@ usage_text[] = {
 "  -xb<addr> Sets the address from which a suitable start for the heap memory",
 "            will be searched from. This is useful if the default address",
 "            clashes with some third-party library.",
+"  -xn       Use the non-moving collector for the old generation.",
 "  -m<n>     Minimum % of heap which must be available (default 3%)",
 "  -G<n>     Number of generations (default: 2)",
 "  -c<n>     Use in-place compaction instead of copying in the oldest generation",
@@ -399,6 +402,7 @@ usage_text[] = {
 "  -Dw  DEBUG: weak",
 "  -DG  DEBUG: gccafs",
 "  -Dg  DEBUG: gc",
+"  -Dn  DEBUG: non-moving gc",
 "  -Db  DEBUG: block",
 "  -DS  DEBUG: sanity",
 "  -Dt  DEBUG: stable",
@@ -1517,6 +1521,12 @@ error = true;
                     break;
 #endif
 
+                case 'n':
+                    OPTION_SAFE;
+                    RtsFlags.GcFlags.useNonmoving = true;
+                    unchecked_arg_start++;
+                    break;
+
                 case 'c': /* Debugging tool: show current cost centre on
                            an exception */
                     OPTION_SAFE;
@@ -1690,6 +1700,16 @@ static void normaliseRtsOpts (void)
     if (RtsFlags.MiscFlags.generate_dump_file) {
         RtsFlags.MiscFlags.install_seh_handlers = true;
     }
+
+    if (RtsFlags.GcFlags.useNonmoving && RtsFlags.GcFlags.generations == 1) {
+        barf("The non-moving collector doesn't support -G1");
+    }
+
+    if (RtsFlags.GcFlags.compact && RtsFlags.GcFlags.useNonmoving) {
+        errorBelch("The non-moving collector cannot be used in conjunction with\n"
+                   "the compacting collector.");
+        errorUsage();
+    }
 }
 
 static void errorUsage (void)
@@ -1841,6 +1861,9 @@ static void read_debug_flags(const char* arg)
         case 'g':
             RtsFlags.DebugFlags.gc = true;
             break;
+        case 'n':
+            RtsFlags.DebugFlags.nonmoving_gc = true;
+            break;
         case 'b':
             RtsFlags.DebugFlags.block_alloc = true;
             break;