Commit 859ebdd4 authored by KevinBuhr's avatar KevinBuhr Committed by Marge Bot

Add "-Iw" RTS flag for minimum wait between idle GCs (#11134)

parent d710fd66
......@@ -653,6 +653,26 @@ performance.
This is an experimental feature, please let us know if it causes
problems and/or could benefit from further tuning.
.. rts-flag:: -Iw ⟨seconds⟩
:default: 0 seconds
.. index::
single: idle GC
By default, if idle GC is enabled in the threaded runtime, a major
GC will be performed every time the process goes idle for a
sufficiently long duration (see :rts-flag:`-I ⟨seconds⟩`). For
large server processes accepting regular but infrequent requests
(e.g., once per second), an expensive, major GC may run after
every request. As an alternative to shutting off idle GC entirely
(with ``-I0``), a minimum wait time between idle GCs can be
specified with this flag. For example, ``-Iw60`` will ensure that
an idle GC runs at most once per minute.
This is an experimental feature, please let us know if it causes
problems and/or could benefit from further tuning.
.. rts-flag:: -ki ⟨size⟩
:default: 1k
......
......@@ -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
......@@ -1179,19 +1180,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