{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE TypeFamilies #-} module Main (main) where import Control.DeepSeq import Control.Eff import Control.Eff.Concurrent import Control.Monad (replicateM) import qualified Criterion.Main as Criterion import Criterion.Types ( bench, bgroup, nfAppIO, ) import Data.Dynamic import GHC.Stack main = Criterion.defaultMain [ bgroup "unidirectionalMessagePassing" [ bench ( "n=" <> show noMessages <> ": " <> show senderNo <> " -> " <> show receiverNo ) ( nfAppIO unidirectionalMessagePassing (senderNo, noMessages, receiverNo) ) | noMessages <- [100000], (senderNo, receiverNo) <- [ (1, 1000) -- (10, 100), -- (1, 1), -- (1000, 1) ] ] ] mkTestMessage :: Int -> TestMessage mkTestMessage !i = MkTestMessage ( "The not so very very very very very very very very very very very very very very very very very very very very very very very very " ++ show i, "large", "meeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeessssssssssssssssssssssssssssssssss" ++ show i, ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", even i, 123423421111111111111111111123234 * toInteger i ) ) newtype TestMessage = MkTestMessage ([Char], [Char], [Char], ([Char], [Char], Bool, Integer)) deriving newtype (Show, NFData, Typeable) unidirectionalMessagePassing :: HasCallStack => (Int, Int, Int) -> IO () unidirectionalMessagePassing (!np, !nm, !nc) = defaultMainWithLogWriter noOpLogWriter $ do cs <- consumers ps <- producers cs awaitAllDown cs awaitAllDown ps where producers !cs = replicateM nc (spawn "producer" produce) where produce = mapM_ (uncurry (flip sendMessage)) ((,) <$> (mkTestMessage <$> [0 .. (nm `div` (nc * np)) - 1]) <*> cs) consumers = do replicateM nc (spawn "consumer" (consume (nm `div` nc))) where consume 0 = return () consume workLeft = do (MkTestMessage !_msg) <- receiveMessage consume (workLeft - 1) awaitAllDown :: [ProcessId] -> Eff Effects () awaitAllDown [] = return () awaitAllDown (p : rest) = do m <- monitor p _ <- receiveSelectedMessage (selectProcessDown m) awaitAllDown rest