■ ■ ■ ■ ■ ■
server/src-lib/Hasura/GC.hs
skipped 6 lines 7 7 import GHC.Stats 8 8 import Hasura.Logging 9 9 import Hasura.Prelude 10 - import System.Mem (performMajorGC) 10 + import System.Mem (performMajorGC, performMinorGC ) 11 11 12 12 -- | The RTS's idle GC doesn't work for us: 13 13 -- skipped 20 lines 34 34 DiffTime -> 35 35 IO void 36 36 ourIdleGC (Logger logger) idleInterval minGCInterval maxNoGCInterval = 37 - startTimer >>= go 0 0 37 + startTimer >>= go 0 0 False 38 38 where 39 - go gcs_prev major_gcs_prev timerSinceLastMajorGC = do 39 + go gcs_prev major_gcs_prev lastIterationPerformedGC timerSinceLastMajorGC = do 40 40 timeSinceLastGC <- timerSinceLastMajorGC 41 41 when (timeSinceLastGC < minGCInterval) $ do 42 42 -- no need to check idle until we've passed the minGCInterval: skipped 6 lines 49 49 let areIdle = gcs == gcs_prev 50 50 areOverdue = timeSinceLastGC > maxNoGCInterval 51 51 52 - -- a major GC was run since last iteration (cool!), reset timer: 53 52 if 54 - | major_gcs > major_gcs_prev -> do 55 - startTimer >>= go gcs major_gcs 53 + -- a major GC was run since last iteration (cool!), reset timer: 54 + | major_gcs > major_gcs_prev -> do 55 + startTimer >>= go gcs major_gcs False 56 56 57 - -- we are idle and its a good time to do a GC, or we're overdue and must run a GC: 58 - | areIdle || areOverdue -> do 59 - when (areOverdue && not areIdle) $ 60 - logger $ 61 - UnstructuredLog LevelWarn $ 62 - "Overdue for a major GC: forcing one even though we don't appear to be idle" 63 - performMajorGC 64 - startTimer >>= go (gcs + 1) (major_gcs + 1) 57 + -- we are idle and its a good time to do a GC, or we're overdue and must run a GC: 58 + | areIdle || areOverdue -> do 59 + -- If we performed a GC last time and nothing was promoted meantime 60 + -- (minor GCs are the same) running a cheaper minor GC should 61 + -- suffice to perform any new due finalizers: 62 + if lastIterationPerformedGC && areIdle 63 + then do 64 + performMinorGC 65 + startTimer >>= go (gcs + 1) major_gcs True 66 + else do 67 + when (areOverdue && not areIdle) 68 + $ logger 69 + $ UnstructuredLog LevelWarn 70 + $ "Overdue for a major GC: forcing one even though we don't appear to be idle" 71 + performMajorGC 72 + startTimer >>= go (gcs + 1) (major_gcs + 1) True 65 73 66 74 -- else keep the timer running, waiting for us to go idle: 67 75 | otherwise -> do 68 76 C.sleep idleInterval 69 - go gcs major_gcs timerSinceLastMajorGC 77 + go gcs major_gcs False timerSinceLastMajorGC 70 78