Commit 04dce498 authored by KevinBuhr's avatar KevinBuhr Committed by Ben Gamari

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 859ebdd4)
parent 308fe4db
Pipeline #22022 failed with stages
in 416 minutes
......@@ -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 */
......
......@@ -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;
......
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment