@@ -347,7 +347,7 @@ data SVar t m a = SVar
347 , enqueue :: t m a -> IO ()
347 , enqueue :: t m a -> IO ()
348 , isWorkDone :: IO Bool
348 , isWorkDone :: IO Bool
349 , needDoorBell :: IORef Bool
349 , needDoorBell :: IORef Bool
350− , workLoop :: WorkerInfo -> m ()
350+ , workLoop :: Maybe WorkerInfo -> m ()
352 -- Shared, thread tracking
352 -- Shared, thread tracking
353 , workerThreads :: IORef (Set ThreadId)
353 , workerThreads :: IORef (Set ThreadId)
@@ -905,13 +905,16 @@ workerRateControl sv yinfo winfo = do
905-- streams. latency update must be done when we yield directly to outputQueue
905-- streams. latency update must be done when we yield directly to outputQueue
906-- or when we yield to heap.
906-- or when we yield to heap.
907{-# INLINE sendYield #-}
907{-# INLINE sendYield #-}
908−sendYield :: SVar t m a -> WorkerInfo -> ChildEvent a -> IO Bool
908+sendYield :: SVar t m a -> Maybe WorkerInfo -> ChildEvent a -> IO Bool
909−sendYield sv winfo msg = do
909+sendYield sv mwinfo msg = do
910 r <- send sv msg
910 r <- send sv msg
911 rateLimitOk <-
911 rateLimitOk <-
912− case yieldRateInfo sv of
914+ case yieldRateInfo sv of
915+ Nothing -> return True
916+ Just yinfo -> workerRateControl sv yinfo winfo
913 Nothing -> return True
917 Nothing -> return True
914− Just yinfo -> workerRateControl sv yinfo winfo
915 return $ r && rateLimitOk
918 return $ r && rateLimitOk
917{-# INLINE workerStopUpdate #-}
920{-# INLINE workerStopUpdate #-}
@@ -921,12 +924,15 @@ workerStopUpdate winfo info = do
921 when (i /= 0) $ workerUpdateLatency info winfo
924 when (i /= 0) $ workerUpdateLatency info winfo
923{-# INLINABLE sendStop #-}
926{-# INLINABLE sendStop #-}
924−sendStop :: SVar t m a -> WorkerInfo -> IO ()
927+sendStop :: SVar t m a -> Maybe WorkerInfo -> IO ()
925−sendStop sv winfo = do
928+sendStop sv mwinfo = do
926 atomicModifyIORefCAS_ (workerCount sv) $ \n -> n - 1
929 atomicModifyIORefCAS_ (workerCount sv) $ \n -> n - 1
927− case yieldRateInfo sv of
932+ case yieldRateInfo sv of
933+ Nothing -> return ()
934+ Just info -> workerStopUpdate winfo info
928 Nothing -> return ()
935 Nothing -> return ()
929− Just info -> workerStopUpdate winfo info
930 myThreadId >>= \tid -> void $ send sv (ChildStop tid Nothing)
936 myThreadId >>= \tid -> void $ send sv (ChildStop tid Nothing)
932-------------------------------------------------------------------------------
938-------------------------------------------------------------------------------
@@ -1193,17 +1199,20 @@ pushWorker yieldMax sv = do
1193#ifdef DIAGNOSTICS
1199#ifdef DIAGNOSTICS
1194 recordMaxWorkers sv
1200 recordMaxWorkers sv
1196− -- XXX we can make this allocation conditional, it might matter when
1197− -- significant number of workers are being sent.
1202+ -- This allocation matters when significant number of workers are being
1203+ -- sent. We allocate it only when needed.
1198− winfo <- do
1204+ winfo <-
1205+ case yieldRateInfo sv of
1206+ Nothing -> return Nothing
1207+ Just _ -> liftIO $ do
1199− cntRef <- liftIO $ newIORef 0
1208+ cntRef <- newIORef 0
1200− t <- liftIO $ getTime Monotonic
1209+ t <- getTime Monotonic
1201− lat <- liftIO $ newIORef (0, t)
1210+ lat <- newIORef (0, t)
1202− return $ WorkerInfo
1211+ return $ Just $ WorkerInfo
1203− { workerYieldMax = yieldMax
1212+ { workerYieldMax = yieldMax
1204− , workerYieldCount = cntRef
1213+ , workerYieldCount = cntRef
1205− , workerLatencyStart = lat
1214+ , workerLatencyStart = lat
1207 doFork (workLoop sv winfo) (handleChildException sv) >>= addThread sv
1216 doFork (workLoop sv winfo) (handleChildException sv) >>= addThread sv
1209-- XXX we can push the workerCount modification in accountThread and use the
1218-- XXX we can push the workerCount modification in accountThread and use the
@@ -1215,25 +1224,32 @@ pushWorker yieldMax sv = do
1215-- workerThreads. Alternatively, we can use a CreateThread event to avoid
1224-- workerThreads. Alternatively, we can use a CreateThread event to avoid
1216-- using a CAS based modification.
1225-- using a CAS based modification.
1217{-# NOINLINE pushWorkerPar #-}
1226{-# NOINLINE pushWorkerPar #-}
1218−pushWorkerPar :: MonadAsync m => SVar t m a -> (WorkerInfo -> m ()) -> m ()
1227+pushWorkerPar :: MonadAsync m => SVar t m a -> (Maybe WorkerInfo -> m ()) -> m ()
1219pushWorkerPar sv wloop = do
1228pushWorkerPar sv wloop = do
1220 -- We do not use workerCount in case of ParallelVar but still there is no
1229 -- We do not use workerCount in case of ParallelVar but still there is no
1221 -- harm in maintaining it correctly.
1230 -- harm in maintaining it correctly.
1222#ifdef DIAGNOSTICS
1231#ifdef DIAGNOSTICS
1223 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
1232 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
1224 recordMaxWorkers sv
1233 recordMaxWorkers sv
1225−#endif
1234+ -- This allocation matters when significant number of workers are being
1235+ -- sent. We allocate it only when needed. The overhead increases by 4x.
1226− winfo <- do
1236+ winfo <-
1237+ case yieldRateInfo sv of
1238+ Nothing -> return Nothing
1239+ Just _ -> liftIO $ do
1227− cntRef <- liftIO $ newIORef 0
1240+ cntRef <- newIORef 0
1228− t <- liftIO $ getTime Monotonic
1241+ t <- getTime Monotonic
1229− lat <- liftIO $ newIORef (0, t)
1242+ lat <- newIORef (0, t)
1230− return $ WorkerInfo
1243+ return $ Just $ WorkerInfo
1231− { workerYieldMax = 0
1244+ { workerYieldMax = 0
1232− , workerYieldCount = cntRef
1245+ , workerYieldCount = cntRef
1233− , workerLatencyStart = lat
1246+ , workerLatencyStart = lat
1236 doFork (wloop winfo) (handleChildException sv) >>= modifyThread sv
1249 doFork (wloop winfo) (handleChildException sv) >>= modifyThread sv
1251+ doFork (wloop Nothing) (handleChildException sv) >>= modifyThread sv
1238-- Returns:
1254-- Returns:
1239-- True: can dispatch more
1255-- True: can dispatch more
@@ -1860,7 +1876,7 @@ getAheadSVar :: MonadAsync m
1860 -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1876 -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
1861 -> State t m a
1877 -> State t m a
1862 -> SVar t m a
1878 -> SVar t m a
1863− -> WorkerInfo
1879+ -> Maybe WorkerInfo
1864 -> m ())
1880 -> m ())
1865 -> IO (SVar t m a)
1881 -> IO (SVar t m a)
1866getAheadSVar st f = do
1882getAheadSVar st f = do
@@ -2050,7 +2066,7 @@ newAheadVar :: MonadAsync m
2050 -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
2066 -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Int)
2051 -> State t m a
2067 -> State t m a
2052 -> SVar t m a
2068 -> SVar t m a
2053− -> WorkerInfo
2069+ -> Maybe WorkerInfo
2054 -> m ())
2070 -> m ())
2055 -> m (SVar t m a)
2071 -> m (SVar t m a)
2056newAheadVar st m wloop = do
2072newAheadVar st m wloop = do