summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Crayne <jim.crayne@gmail.com>2020-01-23 19:53:41 -0500
committerJoe Crayne <joe@jerkface.net>2020-01-24 03:01:27 -0500
commit5f2252d21c9996fe6b23654e53c613817ae3b292 (patch)
treeb3daf6e99c3de77aa1f8297efd7b5caa9a4d4d71
parentfead89918f61272998e968397ad51de097d197ea (diff)
thread instrumentation: contention reduction experiment
-rw-r--r--lifted-concurrent/lifted-concurrent.cabal1
-rw-r--r--lifted-concurrent/src/Control/Concurrent/Lifted/Instrument.hs52
2 files changed, 33 insertions, 20 deletions
diff --git a/lifted-concurrent/lifted-concurrent.cabal b/lifted-concurrent/lifted-concurrent.cabal
index 26e9df68..78a027db 100644
--- a/lifted-concurrent/lifted-concurrent.cabal
+++ b/lifted-concurrent/lifted-concurrent.cabal
@@ -25,6 +25,7 @@ library
25 other-extensions: FlexibleContexts 25 other-extensions: FlexibleContexts
26 build-depends: 26 build-depends:
27 base 27 base
28 , vector
28 , containers 29 , containers
29 , time 30 , time
30 , lifted-async 31 , lifted-async
diff --git a/lifted-concurrent/src/Control/Concurrent/Lifted/Instrument.hs b/lifted-concurrent/src/Control/Concurrent/Lifted/Instrument.hs
index bd6ee4b8..b4a67583 100644
--- a/lifted-concurrent/src/Control/Concurrent/Lifted/Instrument.hs
+++ b/lifted-concurrent/src/Control/Concurrent/Lifted/Instrument.hs
@@ -27,7 +27,9 @@ import Data.Time()
27import Data.Time.Clock 27import Data.Time.Clock
28import DPut 28import DPut
29import DebugTag 29import DebugTag
30 30import qualified Data.Vector as V
31import Data.Vector (Vector)
32import Data.Char
31 33
32data PerThread = PerThread 34data PerThread = PerThread
33 { lbl :: String 35 { lbl :: String
@@ -35,15 +37,25 @@ data PerThread = PerThread
35 } 37 }
36 deriving (Eq,Ord,Show) 38 deriving (Eq,Ord,Show)
37 39
40{-# NOINLINE globalMVarArray #-}
41globalMVarArray :: Vector (MVar (Map.Map ThreadId PerThread))
42globalMVarArray = unsafePerformIO (sequence (V.replicate 256 (newMVar Map.empty)))
43
38data GlobalState = GlobalState 44data GlobalState = GlobalState
39 { threads :: !(Map.Map ThreadId PerThread) 45 { reportException :: String -> IO ()
40 , reportException :: String -> IO ()
41 } 46 }
42 47
48hashThreadId :: ThreadId -> Int
49hashThreadId tid = hash 0 (dropThreadIdAndSPace (show tid))
50 where
51 dropThreadIdAndSPace ('T':'h':'r':'e':'a':'d':'I':'d':' ':xs) = xs
52 dropThreadIdAndSPace xs = xs
53 hash n xs = read xs `mod` 256
54
55
43globals :: MVar GlobalState 56globals :: MVar GlobalState
44globals = unsafePerformIO $ newMVar $ GlobalState 57globals = unsafePerformIO $ newMVar $ GlobalState
45 { threads = Map.empty 58 { reportException = dput XMisc
46 , reportException = dput XMisc
47 } 59 }
48{-# NOINLINE globals #-} 60{-# NOINLINE globals #-}
49 61
@@ -92,24 +104,25 @@ instrumented rawFork action = do
92 t <- mask_ $ rawFork $ \unmask -> do 104 t <- mask_ $ rawFork $ \unmask -> do
93 tid <- myThreadId 105 tid <- myThreadId
94 let scrapIt = do takeMVar mvar 106 let scrapIt = do takeMVar mvar
95 modifyThreads $! Map.delete tid 107 modifyThreads tid $! Map.delete tid
96 io <- catch (unmask action >> return scrapIt) $ \e -> case fromException e of 108 io <- catch (unmask action >> return scrapIt) $ \e -> case fromException e of
97 Just ThreadKilled -> return scrapIt 109 Just ThreadKilled -> return scrapIt
98 Nothing -> liftBase $ do 110 Nothing -> liftBase $ do
99 g <- takeMVar globals 111 g <- readMVar globals
112 mp <- readMVar (globalMVarArray V.! hashThreadId tid)
100 let l = concat [ show e 113 let l = concat [ show e
101 , " (" 114 , " ("
102 , maybe "" lbl $ Map.lookup tid (threads g) 115 , maybe "" lbl $ Map.lookup tid mp
103 , ")" 116 , ")"
104 ] 117 ]
105 reportException g l 118 reportException g l
106 let l = concat [ show e 119 let l = concat [ show e
107 , " (" 120 , " ("
108 , maybe "" lbl $ Map.lookup tid (threads g) 121 , maybe "" lbl $ Map.lookup tid mp
109 , ")" 122 , ")"
110 ] 123 ]
111 foldr seq (return ()) l 124 foldr seq (return ()) l
112 putMVar globals $! g { threads = Map.insert tid (PerThread l tm) $ threads g } 125 modifyThreads tid $! Map.insert tid (PerThread l tm)
113 return $ return () -- Remove the thread only if it terminated normally or was killed. 126 return $ return () -- Remove the thread only if it terminated normally or was killed.
114 io -- scrap record on normal termination 127 io -- scrap record on normal termination
115 liftBase $ labelThread_ t (defaultLabel callStack) tm 128 liftBase $ labelThread_ t (defaultLabel callStack) tm
@@ -122,25 +135,24 @@ labelThread_ tid s tm = do
122 GHC.labelThread tid s 135 GHC.labelThread tid s
123 let updateIt (Just pt) = Just $ pt { lbl = s } 136 let updateIt (Just pt) = Just $ pt { lbl = s }
124 updateIt Nothing = Just $ PerThread s tm 137 updateIt Nothing = Just $ PerThread s tm
125 modifyThreads $! Map.alter updateIt tid 138 modifyThreads tid $! Map.alter updateIt tid
126 139
127labelThread :: ThreadId -> String -> IO () 140labelThread :: ThreadId -> String -> IO ()
128labelThread tid s = do 141labelThread tid s = do
129 foldr seq (return ()) s 142 foldr seq (return ()) s
130 GHC.labelThread tid s 143 GHC.labelThread tid s
131 modifyThreads $! Map.adjust (\pt -> pt { lbl = s }) tid 144 modifyThreads tid $! Map.adjust (\pt -> pt { lbl = s }) tid
132{-# INLINE labelThread #-} 145{-# INLINE labelThread #-}
133 146
134threadsInformation :: IO [(ThreadId,PerThread)] 147threadsInformation :: IO [(ThreadId,PerThread)]
135threadsInformation = do 148threadsInformation = do
136 m <- threads <$> readMVar globals 149 ms <- mapM readMVar (V.toList globalMVarArray)
137 return $ Map.toList m 150 return $ Prelude.concatMap Map.toList ms
138 151
139 152
140modifyThreads :: MonadBaseControl IO m => 153modifyThreads :: MonadBaseControl IO m => ThreadId ->
141 (Map.Map ThreadId PerThread -> Map.Map ThreadId PerThread) -> m () 154 (Map.Map ThreadId PerThread -> Map.Map ThreadId PerThread) -> m ()
142modifyThreads f = do 155modifyThreads tid f = do
143 let f' st = st { threads = f (threads st) } 156 let tidHash = hashThreadId tid
144 bracket (takeMVar globals) 157 let mvar = globalMVarArray V.! tidHash
145 (\g -> putMVar globals $! f' g) 158 modifyMVarMasked_ mvar (return . f)
146 (\g -> return ())