Skip to content

Commit 7f7e470

Browse files
committed
improve contention in hls-graph
STM stats are not yet reported in the benchmark suite, so we need to run the benchmarks manually in verbose mode to observ them (and build hls-graph with the stm-stats Cabal flag). cabal build exe:ghcide ghcide-bench && cabal exec cabal run ghcide-bench -- -- -s "edit" --samples 10 --no-clean --example-module Distribution/Simple.hs --example-module Distribution/Types/Module.hs -v Lots of contention in `builder` and esp. `updateReverseDeps`. `incDatabase` should not have any retries, could be a bug. ``` STM transaction statistics (2021-11-30 16:51:48.260905 UTC): Transaction Commits Retries Ratio _anonymous_ 5 0 0.00 builder 80886 6000 0.07 compute 19175 141 0.01 incDatabase 27 100 3.70 updateReverseDeps 3827 765 0.20 ``` ``` STM transaction statistics (2021-11-30 19:45:30.904126927 UTC): Transaction Commits Retries Ratio _anonymous_ 1 0 0.00 builder 606254 22569 0.04 compute 324708 10428 0.03 incDatabase 15 0 0.00 updateReverseDeps 259755 489285 1.88 ``` ``` STM transaction statistics (2021-11-30 20:21:57.968789 UTC): Transaction Commits Retries Ratio _anonymous_ 48318 2 0.00 builder 1108126 1276 0.00 compute 22423 144 0.01 updateReverseDeps 65225 377 0.01 ``` ``` STM transaction statistics (2021-11-30 19:57:27.979412261 UTC): Transaction Commits Retries Ratio _anonymous_ 294 0 0.00 builder 861431 2914 0.00 compute 324708 1573 0.00 updateReverseDeps 858100 17816 0.02 ```
1 parent e513593 commit 7f7e470

File tree

2 files changed

+12
-13
lines changed

2 files changed

+12
-13
lines changed

hls-graph/src/Development/IDE/Graph/Database.hs

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ module Development.IDE.Graph.Database(
1212
shakeGetDirtySet,
1313
shakeGetCleanKeys
1414
,shakeGetBuildEdges) where
15-
import Control.Concurrent.STM.Stats (atomicallyNamed,
16-
readTVarIO)
15+
import Control.Concurrent.STM.Stats (readTVarIO)
1716
import Data.Dynamic
1817
import Data.Maybe
1918
import Development.IDE.Graph.Classes ()
@@ -64,7 +63,7 @@ shakeRunDatabaseForKeys
6463
-> [Action a]
6564
-> IO ([a], [IO ()])
6665
shakeRunDatabaseForKeys keysChanged (ShakeDatabase lenAs1 as1 db) as2 = do
67-
atomicallyNamed "incDatabase" $ incDatabase db keysChanged
66+
incDatabase db keysChanged
6867
as <- fmap (drop lenAs1) $ runActions db $ map unvoid as1 ++ as2
6968
return (as, [])
7069

hls-graph/src/Development/IDE/Graph/Internal/Database.hs

+10-10
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,19 @@ newDatabase databaseExtra databaseRules = do
5151
pure Database{..}
5252

5353
-- | Increment the step and mark dirty
54-
incDatabase :: Database -> Maybe [Key] -> STM ()
54+
incDatabase :: Database -> Maybe [Key] -> IO ()
5555
-- only some keys are dirty
5656
incDatabase db (Just kk) = do
57-
modifyTVar' (databaseStep db) $ \(Step i) -> Step $ i + 1
57+
atomically $ modifyTVar' (databaseStep db) $ \(Step i) -> Step $ i + 1
5858
transitiveDirtyKeys <- transitiveDirtySet db kk
59-
for_ transitiveDirtyKeys $ \k ->
59+
for_ transitiveDirtyKeys $ \k -> atomically $
6060
SMap.focus updateDirty k (databaseValues db)
6161

6262
-- all keys are dirty
6363
incDatabase db Nothing = do
64-
modifyTVar' (databaseStep db) $ \(Step i) -> Step $ i + 1
64+
atomically $ modifyTVar' (databaseStep db) $ \(Step i) -> Step $ i + 1
6565
let list = SMap.listT (databaseValues db)
66-
flip ListT.traverse_ list $ \(k,_) -> do
66+
atomicallyNamed "incDatabase" $ flip ListT.traverse_ list $ \(k,_) ->
6767
SMap.focus updateDirty k (databaseValues db)
6868

6969
updateDirty :: Monad m => Focus.Focus KeyDetails m ()
@@ -94,7 +94,7 @@ builder db@Database{..} keys = withRunInIO $ \(RunInIO run) -> do
9494
-- Things that I need to force before my results are ready
9595
toForce <- liftIO $ newTVarIO []
9696
current <- liftIO $ readTVarIO databaseStep
97-
results <- liftIO $ atomicallyNamed "builder" $ for keys $ \id -> do
97+
results <- liftIO $ for keys $ \id -> atomicallyNamed "builder" $ do
9898
-- Spawn the id if needed
9999
status <- SMap.lookup id databaseValues
100100
val <- case viewDirty current $ maybe (Dirty Nothing) keyStatus status of
@@ -215,7 +215,7 @@ updateReverseDeps
215215
-> [Key] -- ^ Previous direct dependencies of Id
216216
-> HashSet Key -- ^ Current direct dependencies of Id
217217
-> IO ()
218-
updateReverseDeps myId db prev new = uninterruptibleMask_ $ atomicallyNamed "updateReverseDeps" $ do
218+
updateReverseDeps myId db prev new = uninterruptibleMask_ $ do
219219
forM_ prev $ \d ->
220220
unless (d `HSet.member` new) $
221221
doOne (HSet.delete myId) d
@@ -224,20 +224,20 @@ updateReverseDeps myId db prev new = uninterruptibleMask_ $ atomicallyNamed "upd
224224
where
225225
alterRDeps f =
226226
Focus.adjust (onKeyReverseDeps f)
227-
doOne f id =
227+
doOne f id = atomicallyNamed "updateReverseDeps" $
228228
SMap.focus (alterRDeps f) id (databaseValues db)
229229

230230
getReverseDependencies :: Database -> Key -> STM (Maybe (HashSet Key))
231231
getReverseDependencies db = (fmap.fmap) keyReverseDeps . flip SMap.lookup (databaseValues db)
232232

233-
transitiveDirtySet :: Foldable t => Database -> t Key -> STM (HashSet Key)
233+
transitiveDirtySet :: Foldable t => Database -> t Key -> IO (HashSet Key)
234234
transitiveDirtySet database = flip State.execStateT HSet.empty . traverse_ loop
235235
where
236236
loop x = do
237237
seen <- State.get
238238
if x `HSet.member` seen then pure () else do
239239
State.put (HSet.insert x seen)
240-
next <- lift $ getReverseDependencies database x
240+
next <- lift $ atomically $ getReverseDependencies database x
241241
traverse_ loop (maybe mempty HSet.toList next)
242242

243243
-- | IO extended to track created asyncs to clean them up when the thread is killed,

0 commit comments

Comments
 (0)