-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
q: design of resource-pool
#37
Comments
It's based on the code from Control.Concurrent.QSem (e.g. this vs this).
Benchmarks are enough ;) benchmark codemodule Main where
import Control.Concurrent
import Control.Monad
import Control.Monad.IO.Class
import Data.Function
import Data.Pool
import GHC.Clock
import Numeric
import System.Environment
timed :: IO a -> IO (a, Double)
timed m = do
t1 <- liftIO getMonotonicTime
a <- m
t2 <- liftIO getMonotonicTime
pure (a, t2 - t1)
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
worker :: Pool Integer -> MVar Int -> MVar Double -> IO ()
worker pool mctr1 mctr2 = forever $ do
(_, t) <- timed $ withResource pool $ \n -> do
pure $! fib n
liftIO $ do
modifyMVar_ mctr1 $ \x -> let z = x + 1 in z `seq` pure z
modifyMVar_ mctr2 $ \x -> let z = max x t in z `seq` pure z
main :: IO ()
main = do
[threads, stripes] <- map (read @Int) <$> getArgs
caps <- getNumCapabilities
mctrs1 <- replicateM threads $ newMVar 0
mctrs2 <- replicateM threads $ newMVar 0
let config = defaultPoolConfig (pure 3) (\_ -> pure ()) 10 100 & setNumStripes (Just stripes)
pool <- newPool config
putStrLn $ "capabilities: " ++ show caps ++ ", threads: " ++ show threads ++ ", stripes: " ++ show stripes
void . forM_ (zipWith (,) mctrs1 mctrs2) $ \(mctr1, mctr2) -> do
forkIO $ do
--liftIO $ putStrLn . show =<< myThreadId
worker pool mctr1 mctr2
_ <- forkIO $ forever $ do
threadDelay 1000000
ctr1 <- sum <$> mapM (\v -> modifyMVar v (\z -> pure (0, z))) mctrs1
ctr2 <- maximum <$> mapM (\v -> modifyMVar v (\z -> pure (0, z))) mctrs2
putStrLn $ show ctr1 ++ " " ++ showFFloat (Just 6) ctr2 ""
void getLine
Throughput can be over 100x greater when you have a stripe per capability and there is no lock contention. That's why it's the default option if you don't explicitly set the number of stripes.
Not quite. We took over maintenance from Brian O'Sullivan, the original author, his implementation was already striped. I can see why it can appear under-documented, from |
Lovely! Thank you for your elaborate answer, that really clarifies it! |
I have had a thorough read of the library and some things alienate me
QSem
, yet there's not a single use ofQSem
throughout the libraryThis also makes it quite hard to use the library - it is not obvious what picking a number of stripes even implies. I understand that this is a work internal library you published so there's no obligation of providing good external documentation but I would still love to see my questions answered.
Thanks in advance!
The text was updated successfully, but these errors were encountered: