Skip to content

Commit 82d3b43

Browse files
committed
Only shuffle 20% of the time
1 parent 6a781b9 commit 82d3b43

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

io-sim/src/Control/Monad/IOSim/Internal.hs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ import Control.Monad.IOSim.Types hiding (SimEvent (SimPOREvent),
8383
Trace (SimPORTrace))
8484
import Control.Monad.IOSim.Types (SimEvent)
8585
import System.Random (StdGen, randomR, split)
86+
import Data.Bifunctor (first)
8687

8788
--
8889
-- Simulation interpreter
@@ -855,31 +856,49 @@ unblockThreads !onlySTM !wakeup !simstate@SimState {runqueue, threads, stdGen} =
855856
(unblocked, simstate {
856857
runqueue = Deque.fromList (shuffledRunqueue ++ rest),
857858
threads = threads',
858-
stdGen = stdGen''
859+
stdGen = stdGen'''
859860
})
860861
where
861-
!(shuffledRunqueue, stdGen'') = fisherYatesShuffle stdGen' toShuffle
862-
!((toShuffle, rest), stdGen') =
863-
let runqueueList = Deque.toList $ runqueue <> Deque.fromList unblocked
864-
runqueueListLength = max 1 (length runqueueList)
865-
(ix, newGen) = randomR (0, runqueueListLength `div` 2) stdGen
866-
in (splitAt ix runqueueList, newGen)
867862
-- can only unblock if the thread exists and is blocked (not running)
868-
!unblocked = [ tid
863+
!timerUnblocked = [ tid
869864
| tid <- wakeup
870865
, case Map.lookup tid threads of
871-
Just Thread { threadStatus = ThreadBlocked BlockedOnSTM }
872-
-> True
873866
Just Thread { threadStatus = ThreadBlocked _ }
874867
-> not onlySTM
875868
_ -> False
876869
]
870+
871+
!stmUnblocked = [ tid
872+
| tid <- wakeup
873+
, case Map.lookup tid threads of
874+
Just Thread { threadStatus = ThreadBlocked BlockedOnSTM }
875+
-> True
876+
_ -> False
877+
]
878+
879+
!unblocked = timerUnblocked ++ stmUnblocked
880+
877881
-- and in which case we mark them as now running
878882
!threads' = List.foldl'
879883
(flip (Map.adjust (\t -> t { threadStatus = ThreadRunning })))
880884
threads
881885
unblocked
882886

887+
-- Shuffle only 1/5th of the time
888+
!(shouldShuffle, stdGen') =
889+
first (== 0) $ randomR (0 :: Int, 5) stdGen
890+
891+
-- Only shuffle at most half of the total runqueue
892+
!((toShuffle, rest), stdGen'')
893+
| shouldShuffle =
894+
let runqueueList = Deque.toList $ runqueue <> Deque.fromList unblocked
895+
runqueueListLength = max 1 (length runqueueList)
896+
(ix, newGen) = randomR (0, runqueueListLength `div` 2) stdGen'
897+
in (splitAt ix runqueueList, newGen)
898+
| otherwise = (([], Deque.toList $ runqueue <> Deque.fromList unblocked), stdGen')
899+
900+
!(shuffledRunqueue, stdGen''') = fisherYatesShuffle stdGen'' toShuffle
901+
883902
-- Fisher-Yates shuffle implementation
884903
fisherYatesShuffle :: StdGen -> [a] -> ([a], StdGen)
885904
fisherYatesShuffle gen [] = ([], gen)

0 commit comments

Comments
 (0)