packages feed

parallel-io-0.3.0.2: Control/Concurrent/ParallelIO/Fuzz.hs

module Main where

import Data.IORef
import qualified Numeric

import System.Random

import Control.Concurrent
import Control.Concurrent.ParallelIO.Local

import Control.Monad


-- | Range for number of threads to spawn
sPAWN_RANGE = (0, 100)

-- | Delay range in microseconds
dELAY_RANGE = (0, 1000000)

-- | Out of 100 parallel actions, how many should recursively spawn?
sPAWN_PERCENTAGE :: Int
sPAWN_PERCENTAGE = 2

-- | Number of threads to have processing work items
mAX_WORKERS = 3


showFloat :: RealFloat a => a -> String
showFloat x = Numeric.showFFloat (Just 2) x ""


expected :: Fractional b => (Int, Int) -> b
expected (top, bottom) = fromIntegral (top + bottom) / 2

main :: IO ()
main = do
    -- Birth rate is the rate at which new work items enter the queue
    putStrLn $ "Expected birth rate: " ++ showFloat ((expected sPAWN_RANGE * (fromIntegral sPAWN_PERCENTAGE / 100) * fromIntegral mAX_WORKERS) / (expected dELAY_RANGE / 1000000) :: Double) ++ " items/second"
    -- Service rate is the rate at which work items are removed from the pool
    putStrLn $ "Expected service rate: " ++ showFloat (fromIntegral mAX_WORKERS / (expected dELAY_RANGE / 1000000) :: Double) ++ " items/second"
    -- We are balanced on average if birth rate == service rate, i.e. expected sPAWN_RANGE * (fromIntegral sPAWN_PERCENTAGE / 100) == 1
    putStrLn $ "Balance factor (should be 1): " ++ showFloat (expected sPAWN_RANGE * (fromIntegral sPAWN_PERCENTAGE / 100) :: Double)
    withPool mAX_WORKERS $ \pool -> forever (fuzz pool)

fuzz pool = do
    n <- randomRIO sPAWN_RANGE
    tid <- myThreadId
    putStrLn $ show tid ++ ":\t" ++ show n
    parallel_ pool $ flip map [1..n] $ \i -> do
        should_spawn <- fmap (<= sPAWN_PERCENTAGE) $ randomRIO (1, 100)
        nested_tid <- myThreadId
        
        putStrLn $ show nested_tid ++ ":\trunning " ++ show i ++ if should_spawn then " (recursing)" else ""
        
        randomRIO dELAY_RANGE >>= threadDelay
        
        putStrLn $ show nested_tid ++ ":\twoke up"
        
        when should_spawn $ fuzz pool