@@ -53,7 +53,6 @@ module Development.IDE.Core.Shake(
5353 GlobalIdeOptions (.. ),
5454 HLS. getClientConfig ,
5555 getPluginConfig ,
56- garbageCollect ,
5756 knownTargets ,
5857 setPriority ,
5958 ideLogger ,
@@ -75,7 +74,7 @@ module Development.IDE.Core.Shake(
7574 HieDbWriter (.. ),
7675 VFSHandle (.. ),
7776 addPersistentRule
78- ) where
77+ , garbageCollectDirtyKeys ) where
7978
8079import Control.Concurrent.Async
8180import Control.Concurrent.STM
@@ -109,15 +108,19 @@ import Development.IDE.Core.PositionMapping
109108import Development.IDE.Core.ProgressReporting
110109import Development.IDE.Core.RuleTypes
111110import Development.IDE.Core.Tracing
112- import Development.IDE.GHC.Compat (NameCacheUpdater ( .. ) ,
113- upNameCache , NameCache ,
111+ import Development.IDE.GHC.Compat (NameCache ,
112+ NameCacheUpdater ( .. ) ,
114113 initNameCache ,
114+ knownKeyNames ,
115115 mkSplitUniqSupply ,
116- knownKeyNames )
116+ upNameCache )
117117import Development.IDE.GHC.Orphans ()
118118import Development.IDE.Graph hiding (ShakeValue )
119119import qualified Development.IDE.Graph as Shake
120- import Development.IDE.Graph.Database
120+ import Development.IDE.Graph.Database (ShakeDatabase ,
121+ shakeOpenDatabase ,
122+ shakeProfileDatabase ,
123+ shakeRunDatabaseForKeys )
121124import Development.IDE.Graph.Rule
122125import Development.IDE.Types.Action
123126import Development.IDE.Types.Diagnostics
@@ -157,6 +160,10 @@ import Ide.Plugin.Config
157160import qualified Ide.PluginUtils as HLS
158161import Ide.Types (PluginId )
159162
163+ -- | Maximum age (in # builds) of a cached value after which it's considered garbage
164+ garbageAge :: Int
165+ garbageAge = 100
166+
160167-- | We need to serialize writes to the database, so we send any function that
161168-- needs to write to the database over the channel, where it will be picked up by
162169-- a worker thread.
@@ -325,10 +332,10 @@ lastValueIO s@ShakeExtras{positionMapping,persistentKeys,state} k file = do
325332 MaybeT $ pure $ (,del,ver) <$> fromDynamic dv
326333 case mv of
327334 Nothing -> do
328- void $ modifyVar' state $ HMap. alter (alterValue $ Failed True ) (file, Key k )
335+ void $ modifyVar' state $ HMap. alter (alterValue $ Failed True ) (toKey k file )
329336 return Nothing
330337 Just (v,del,ver) -> do
331- void $ modifyVar' state $ HMap. alter (alterValue $ Stale (Just del) ver (toDyn v)) (file, Key k )
338+ void $ modifyVar' state $ HMap. alter (alterValue $ Stale (Just del) ver (toDyn v)) (toKey k file )
332339 return $ Just (v,addDelta del $ mappingForVersion allMappings file ver)
333340
334341 -- We got a new stale value from the persistent rule, insert it in the map without affecting diagnostics
@@ -339,7 +346,7 @@ lastValueIO s@ShakeExtras{positionMapping,persistentKeys,state} k file = do
339346 -- Something already succeeded before, leave it alone
340347 _ -> old
341348
342- case HMap. lookup (file, Key k ) hm of
349+ case HMap. lookup (toKey k file ) hm of
343350 Nothing -> readPersistent
344351 Just (ValueWithDiagnostics v _) -> case v of
345352 Succeeded ver (fromDynamic -> Just v) -> pure (Just (v, mappingForVersion allMappings file ver))
@@ -417,7 +424,7 @@ setValues :: IdeRule k v
417424 -> Vector FileDiagnostic
418425 -> IO ()
419426setValues state key file val diags =
420- void $ modifyVar' state $ HMap. insert (file, Key key) (ValueWithDiagnostics (fmap toDyn val) diags)
427+ void $ modifyVar' state $ HMap. insert (toKey key file ) (ValueWithDiagnostics (fmap toDyn val) diags)
421428
422429
423430-- | Delete the value stored for a given ide build key
@@ -428,7 +435,7 @@ deleteValue
428435 -> NormalizedFilePath
429436 -> IO ()
430437deleteValue ShakeExtras {dirtyKeys, state} key file = do
431- void $ modifyVar' state $ HMap. delete (file, Key key)
438+ void $ modifyVar' state $ HMap. delete (toKey key file )
432439 atomicModifyIORef_ dirtyKeys $ HSet. insert (toKey key file)
433440
434441recordDirtyKeys
@@ -450,7 +457,7 @@ getValues ::
450457 IO (Maybe (Value v , Vector FileDiagnostic ))
451458getValues state key file = do
452459 vs <- readVar state
453- case HMap. lookup (file, Key key) vs of
460+ case HMap. lookup (toKey key file ) vs of
454461 Nothing -> pure Nothing
455462 Just (ValueWithDiagnostics v diagsV) -> do
456463 let r = fmap (fromJust . fromDynamic @ v ) v
@@ -727,20 +734,25 @@ getHiddenDiagnostics IdeState{shakeExtras = ShakeExtras{hiddenDiagnostics}} = do
727734 val <- readVar hiddenDiagnostics
728735 return $ getAllDiagnostics val
729736
730- -- | Clear the results for all files that do not match the given predicate.
731- garbageCollect :: (NormalizedFilePath -> Bool ) -> Action ()
732- garbageCollect keep = do
733- ShakeExtras {state, diagnostics,hiddenDiagnostics,publishedDiagnostics,positionMapping} <- getShakeExtras
734- liftIO $
735- do newState <- modifyVar' state $ HMap. filterWithKey (\ (file, _) _ -> keep file)
736- void $ modifyVar' diagnostics $ filterDiagnostics keep
737- void $ modifyVar' hiddenDiagnostics $ filterDiagnostics keep
738- void $ modifyVar' publishedDiagnostics $ HMap. filterWithKey (\ uri _ -> keep (fromUri uri))
739- let versionsForFile =
740- HMap. fromListWith Set. union $
741- mapMaybe (\ ((file, _key), ValueWithDiagnostics v _) -> (filePathToUri' file,) . Set. singleton <$> valueVersion v) $
742- HMap. toList newState
743- void $ modifyVar' positionMapping $ filterVersionMap versionsForFile
737+ garbageCollectDirtyKeys :: Action ()
738+ garbageCollectDirtyKeys = do
739+ start <- liftIO offsetTime
740+ dirtySet <- fromMaybe [] <$> getDirtySet
741+ extras <- getShakeExtras
742+ (n:: Int , garbage ) <- liftIO $ modifyVar (state extras) $ \ vmap ->
743+ evaluate $ foldl' removeDirtyKey (vmap, (0 ,[] )) dirtySet
744+ liftIO $ atomicModifyIORef_ (dirtyKeys extras) $ \ x ->
745+ foldl' (flip HSet. insert) x garbage
746+ t <- liftIO start
747+ when (n> 0 ) $ liftIO $ logDebug (logger extras) $ T. pack $
748+ " Garbage collected " <> show n <> " keys (took " <> showDuration t <> " )"
749+ where
750+ -- removeDirtyKey :: (Values, Int) -> (Key, Int) -> (Values, [Key], Int)
751+ removeDirtyKey (vmap,(counter, keys)) (k, age)
752+ | age > garbageAge
753+ , (True , vmap') <- HMap. alterF (\ prev -> (isJust prev, Nothing )) k vmap
754+ = let ! c' = counter+ 1 in (vmap', (c', k: keys))
755+ | otherwise = (vmap, (counter, keys))
744756
745757-- | Define a new Rule without early cutoff
746758define
0 commit comments