diff --git a/src/runtime-prototype/README.md b/src/runtime-prototype/README.md index 9cc97991..78c971c2 100644 --- a/src/runtime-prototype/README.md +++ b/src/runtime-prototype/README.md @@ -136,4 +136,8 @@ cabal test #### How to run benchmarks -`cabal bench` +```bash +cabal configure bench \ + --ghc-options='-threaded -rtsopts -with-rtsopts=-N' +cabal bench +``` diff --git a/src/runtime-prototype/bench/Main.hs b/src/runtime-prototype/bench/Main.hs index a135e3d8..d08553d1 100644 --- a/src/runtime-prototype/bench/Main.hs +++ b/src/runtime-prototype/bench/Main.hs @@ -1,53 +1,75 @@ module Main where +import Control.Monad +import Control.Exception import Control.Concurrent import Control.Concurrent.Async import Data.Atomics.Counter -import Data.IORef import StuntDouble ------------------------------------------------------------------------ -client :: AtomicCounter -> IORef Bool -> IO () -client total shutdown = go +client :: AtomicCounter -> IO () +client total = forever go where go :: IO () go = do - b <- readIORef shutdown - if b then return () - else do - -- generate client req - -- execute client req - incrCounter_ 1 total + -- generate client req + -- execute client req + -- XXX: remove + threadDelay 100000 -- 100ms + incrCounter_ 1 total + +reporter :: AtomicCounter -> IO () +reporter total = go 0 + where + go :: Int -> IO () + go last = do + threadDelay 1000000 -- 1s + tot <- readCounter total + putStrLn (concat ["did ", show (tot - last), " ops"]) + go tot + +before :: Int -> AtomicCounter -> IO [Async ()] +before numberOfClients total = + mapM (\i -> async ((if i == 0 then reporter else client) total)) + [0..numberOfClients] + +data StoppingCriteria + = MaxDurationInSecs Int + | MaxOperations Int + | WaitForCtrlCSignal + +run :: AtomicCounter -> StoppingCriteria -> IO () +run _total (MaxDurationInSecs s) = threadDelay (s * 1000000) +run total (MaxOperations maxOps) = go + where + go :: IO () + go = do + c <- readCounter total + if c < maxOps + then do + threadDelay (50 * 1000) -- 50 ms go + else return () +run _total WaitForCtrlCSignal = threadDelay maxBound -reporter :: IO () -reporter = return () +after :: AtomicCounter -> [Async ()] -> IO () +after total pids = do + mapM_ cancel pids + tot <- readCounter total + putStrLn "" + putStrLn ("total ops: " ++ show tot ++ " ops") main :: IO () main = do -- spawn event loop -- deploy SUT - let n = 4 - maxOps = 100 + let numberOfClients = 4 + stop = MaxOperations 100 total <- newCounter 0 - shutdown <- newIORef False - pids <- mapM (\i -> async (if i == 0 then reporter else client total shutdown)) [0..n] - go total maxOps shutdown - mapM_ wait pids - -- print stats - where - go :: AtomicCounter -> Int -> IORef Bool -> IO () - go total maxOps shutdown = go' - where - go' :: IO () - go' = do - c <- readCounter total - if c < maxOps - then do - threadDelay (50 * 1000) -- 50 ms - go' - -- else if maxDuration has elapsed, flip shutdown - else do - writeIORef shutdown True + bracket + (before numberOfClients total) + (after total) + (const (run total stop)) diff --git a/src/runtime-prototype/stunt-double.cabal b/src/runtime-prototype/stunt-double.cabal index 69948fa0..e9f5bef8 100644 --- a/src/runtime-prototype/stunt-double.cabal +++ b/src/runtime-prototype/stunt-double.cabal @@ -124,5 +124,6 @@ benchmark bench , stunt-double -- https://ghc.gitlab.haskell.org/ghc/doc/users_guide/using-concurrent.html - ghc-options: -threaded -rtsopts -with-rtsopts=-N -with-rtsopts=-qa -with-rtsopts=-qm + -- -with-rtsopts=-qa -with-rtsopts=-qm + ghc-options: -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010 \ No newline at end of file