[Git][ghc/ghc][wip/backports] Add "-Iw" RTS flag for minimum wait between idle GCs (#11134)

Ben Gamari gitlab at gitlab.haskell.org
Wed Jul 8 14:45:49 UTC 2020



Ben Gamari pushed to branch wip/backports at Glasgow Haskell Compiler / GHC


Commits:
04dce498 by Kevin Buhr at 2020-07-08T10:45:43-04:00
Add "-Iw" RTS flag for minimum wait between idle GCs (#11134)

This wasn't originally slated for 8.10 but the documentation part of
this patch snuck into the ghc-8.10 branch via a backport. Instead of
backing out the documentation and causing further user confusion I've
opted just to backport this functional change as well.

(cherry picked from commit 859ebdd446eda446d38708a587503c255b58c4c6)

- - - - -


3 changed files:

- includes/rts/Flags.h
- rts/RtsFlags.c
- rts/Timer.c


Changes:

=====================================
includes/rts/Flags.h
=====================================
@@ -66,6 +66,7 @@ typedef struct _GC_FLAGS {
     bool ringBell;
 
     Time    idleGCDelayTime;    /* units: TIME_RESOLUTION */
+    Time    interIdleGCWait;    /* units: TIME_RESOLUTION */
     bool doIdleGC;
 
     Time    longGCSync;         /* units: TIME_RESOLUTION */


=====================================
rts/RtsFlags.c
=====================================
@@ -164,6 +164,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.GcFlags.compactThreshold   = 30.0;
     RtsFlags.GcFlags.sweep              = false;
     RtsFlags.GcFlags.idleGCDelayTime    = USToTime(300000); // 300ms
+    RtsFlags.GcFlags.interIdleGCWait    = 0;
 #if defined(THREADED_RTS)
     RtsFlags.GcFlags.doIdleGC           = true;
 #else
@@ -1180,19 +1181,33 @@ error = true;
                   break;
 
               case 'I': /* idle GC delay */
-                OPTION_UNSAFE;
-                if (rts_argv[arg][2] == '\0') {
-                  /* use default */
-                } else {
-                    Time t = fsecondsToTime(atof(rts_argv[arg]+2));
-                    if (t == 0) {
-                        RtsFlags.GcFlags.doIdleGC = false;
-                    } else {
-                        RtsFlags.GcFlags.doIdleGC = true;
-                        RtsFlags.GcFlags.idleGCDelayTime = t;
-                    }
-                }
-                break;
+                  OPTION_UNSAFE;
+                  switch (rts_argv[arg][2]) {
+                  /* minimum inter-idle GC wait time */
+                  case 'w':
+                      if (rts_argv[arg][3] == '\0') {
+                          /* use default */
+                      } else {
+                          RtsFlags.GcFlags.interIdleGCWait = fsecondsToTime(atof(rts_argv[arg]+3));
+                      }
+                      break;
+                  /* idle delay before GC */
+                  case '\0':
+                      /* use default */
+                      break;
+                  default:
+                      {
+                          Time t = fsecondsToTime(atof(rts_argv[arg]+2));
+                          if (t == 0) {
+                              RtsFlags.GcFlags.doIdleGC = false;
+                          } else {
+                              RtsFlags.GcFlags.doIdleGC = true;
+                              RtsFlags.GcFlags.idleGCDelayTime = t;
+                          }
+                      }
+                      break;
+                  }
+                  break;
 
               case 'T':
                   OPTION_SAFE;


=====================================
rts/Timer.c
=====================================
@@ -28,8 +28,11 @@
 /* ticks left before next pre-emptive context switch */
 static int ticks_to_ctxt_switch = 0;
 
-/* idle ticks left before we perform a GC */
-static int ticks_to_gc = 0;
+/* idle ticks left before GC allowed */
+static int idle_ticks_to_gc = 0;
+
+/* inter-idle GC ticks left before GC allowed  */
+static int inter_gc_ticks_to_gc = 0;
 
 /*
  * Function: handle_tick()
@@ -53,18 +56,21 @@ handle_tick(int unused STG_UNUSED)
   /*
    * If we've been inactive for idleGCDelayTime (set by +RTS
    * -I), tell the scheduler to wake up and do a GC, to check
-   * for threads that are deadlocked.
+   * for threads that are deadlocked.  However, ensure we wait
+   * at least interIdleGCWait (+RTS -Iw) between idle GCs.
    */
   switch (recent_activity) {
   case ACTIVITY_YES:
       recent_activity = ACTIVITY_MAYBE_NO;
-      ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime /
-                    RtsFlags.MiscFlags.tickInterval;
+      idle_ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime /
+                         RtsFlags.MiscFlags.tickInterval;
       break;
   case ACTIVITY_MAYBE_NO:
-      if (ticks_to_gc == 0) {
+      if (idle_ticks_to_gc == 0 && inter_gc_ticks_to_gc == 0) {
           if (RtsFlags.GcFlags.doIdleGC) {
               recent_activity = ACTIVITY_INACTIVE;
+              inter_gc_ticks_to_gc = RtsFlags.GcFlags.interIdleGCWait /
+                                       RtsFlags.MiscFlags.tickInterval;
 #if defined(THREADED_RTS)
               wakeUpRts();
               // The scheduler will call stopTimer() when it has done
@@ -86,7 +92,8 @@ handle_tick(int unused STG_UNUSED)
 #endif
           }
       } else {
-          ticks_to_gc--;
+              if (idle_ticks_to_gc) idle_ticks_to_gc--;
+              if (inter_gc_ticks_to_gc) inter_gc_ticks_to_gc--;
       }
       break;
   default:



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/04dce49825c5124d942846902d97b42c33ca26e7

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/04dce49825c5124d942846902d97b42c33ca26e7
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200708/ae42ec57/attachment-0001.html>


More information about the ghc-commits mailing list