[Git][ghc/ghc][wip/dcoutts/idle-gc-rewrite2] 2 commits: FIXUP for Rewrite the idle GC scheme
Duncan Coutts pushed to branch wip/dcoutts/idle-gc-rewrite2 at Glasgow Haskell Compiler / GHC Commits: 58f7b037 by Duncan Coutts at 2026-06-02T11:22:31+01:00 FIXUP for Rewrite the idle GC scheme - - - - - 86a547fd by Duncan Coutts at 2026-06-02T11:23:28+01:00 Eliminate the second-highest cause of cache line bounces The do_heap_prof_ticks shared variable was being modified frequently even when profiling was not enabled. This was the cause of over 5% of all HITMs on the nofib threads005 benchmark (on 8 cores). - - - - - 4 changed files: - rts/IdleGC.c - rts/Proftimer.c - rts/RtsFlags.c - rts/Schedule.c Changes: ===================================== rts/IdleGC.c ===================================== @@ -48,7 +48,9 @@ The idle GC is also the only occasion when deadlock detection is performed. So note that disabling idle GC with RTS flag `-I0` will also disable deadlock - detection. See Note [Deadlock detection] for further details. + detection. + +TODO: refer to the deadlock detection note for further details, once that note exists. */ /* @@ -209,22 +211,30 @@ static void unpauseTimerUnlessProfiling(void); void initIdleGc(void) { - /* Use division rounding up (a+b-1)/b, to avoid getting 0 ticks, as this - * would give unexpected results. - */ - idlegc_delay_ticks = - (RtsFlags.GcFlags.idleGCDelayTime + RtsFlags.MiscFlags.tickInterval - 1) - / RtsFlags.MiscFlags.tickInterval; + if (RtsFlags.GcFlags.doIdleGC) { + /* Use division rounding up (a+b-1)/b, to avoid getting 0 ticks, as this + * would give unexpected results. + */ + idlegc_delay_ticks = + (RtsFlags.GcFlags.idleGCDelayTime + RtsFlags.MiscFlags.tickInterval - 1) + / RtsFlags.MiscFlags.tickInterval; - inter_idlegc_delay_ticks = - (RtsFlags.GcFlags.interIdleGCWait + RtsFlags.MiscFlags.tickInterval - 1) - / RtsFlags.MiscFlags.tickInterval; + inter_idlegc_delay_ticks = + (RtsFlags.GcFlags.interIdleGCWait + RtsFlags.MiscFlags.tickInterval - 1) + / RtsFlags.MiscFlags.tickInterval; - /* The -Iw<n> parameter is supposed to control times *between* idle GCs, - * not time since program start. So by initialising to the negative of the - * interval then we can do an idle GC almost immediately if needed. - */ - shared_last_idlegc_tick = -inter_idlegc_delay_ticks; + /* The -Iw<n> parameter is supposed to control times *between* idle GCs, + * not time since program start. So by initialising to the negative of the + * interval then we can do an idle GC almost immediately if needed. + */ + shared_last_idlegc_tick = -inter_idlegc_delay_ticks; + } else { + /* When idle GC is disabled, we turn off the timer tick after one tick + * of all caps being idle. + */ + idlegc_delay_ticks = 1; + inter_idlegc_delay_ticks = 0; + } debugTrace(DEBUG_idlegc, "Idle GC (tick %d): initialising, delay ticks = %d," @@ -379,14 +389,14 @@ void handleIdleGcTick(void) */ if (RtsFlags.GcFlags.doIdleGC) { debugTrace(DEBUG_idlegc, "Idle GC (tick %d): transition to PENDING", - RELAXED_LOAD_ALWAYS(&shared_current_tick)); + RELAXED_LOAD_ALWAYS(&shared_current_tick)); RELAXED_STORE_ALWAYS(&shared_idlegc_state, IDLEGC_STATE_PENDING); #if defined(THREADED_RTS) wakeUpRts(); #endif } else { debugTrace(DEBUG_idlegc, "Idle GC (tick %d): transition to DONE", - RELAXED_LOAD_ALWAYS(&shared_current_tick)); + RELAXED_LOAD_ALWAYS(&shared_current_tick)); RELAXED_STORE_ALWAYS(&shared_idlegc_state, IDLEGC_STATE_DONE); } @@ -405,7 +415,7 @@ static void pauseTimerUnlessProfiling(void) #endif { debugTrace(DEBUG_idlegc, "Idle GC (tick %d): pausing the ticker", - RELAXED_LOAD_ALWAYS(&shared_current_tick)); + RELAXED_LOAD_ALWAYS(&shared_current_tick)); stopTimer(); /* Save the time at which we pause, so we can account for ticks missed ===================================== rts/Proftimer.c ===================================== @@ -78,7 +78,10 @@ startHeapProfTimer( void ) void pauseHeapProfTimer ( void ) { - RELAXED_STORE_ALWAYS(&do_heap_prof_ticks, false); + if (RtsFlags.ProfFlags.doHeapProfile && + RtsFlags.ProfFlags.heapProfileIntervalTicks > 0) { + RELAXED_STORE_ALWAYS(&do_heap_prof_ticks, false); + } } ===================================== rts/RtsFlags.c ===================================== @@ -1921,6 +1921,7 @@ static void normaliseRtsOpts (void) if (RtsFlags.MiscFlags.tickInterval == 0) { RtsFlags.ConcFlags.ctxtSwitchTime = 0; RtsFlags.GcFlags.idleGCDelayTime = 0; + RtsFlags.GcFlags.doIdleGC = false; RtsFlags.ProfFlags.heapProfileInterval = 0; } ===================================== rts/Schedule.c ===================================== @@ -1403,9 +1403,9 @@ scheduleNeedHeapProfile( bool ready_to_gc ) { // When we have +RTS -i0 and we're heap profiling, do a census at // every GC. This lets us get repeatable runs for debugging. - if (RELAXED_LOAD(&performHeapProfile) || - (RtsFlags.ProfFlags.heapProfileInterval==0 && - RtsFlags.ProfFlags.doHeapProfile && ready_to_gc)) { + if (RtsFlags.ProfFlags.doHeapProfile + && ((RtsFlags.ProfFlags.heapProfileInterval==0 && ready_to_gc) + || RELAXED_LOAD(&performHeapProfile))) { return true; } else { return false; View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/58a4ce73a867cca8d8076b42d269ddf... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/58a4ce73a867cca8d8076b42d269ddf... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Duncan Coutts (@dcoutts)