{-# LANGUAGE LambdaCase, OverloadedStrings #-} module Channels where -- | Like Latency, but creating lots of channels import System.Environment import Control.Monad (void, forM_, forever, replicateM_) import Control.Concurrent.MVar import Control.Concurrent (forkOS, threadDelay) import Control.Applicative import Control.Distributed.Process import Control.Distributed.Process.Node import Criterion.Measurement import Data.Binary (encode, decode) import Data.ByteString.Char8 (pack) import Network.Transport.ZMQ (createTransport, defaultZMQParameters) import qualified Data.ByteString.Lazy as BSL import Text.Printf pingServer :: Process () pingServer = forever $ do them <- expect sendChan them () -- TODO: should this be automatic? reconnectPort them pingClient :: Int -> ProcessId -> Process () pingClient n them = do replicateM_ n $ do (sc, rc) <- newChan :: Process (SendPort (), ReceivePort ()) send them sc receiveChan rc initialServer :: Process () initialServer = do us <- getSelfPid liftIO $ BSL.writeFile "pingServer.pid" (encode us) pingServer initialClient :: Int -> Process () initialClient n = do them <- liftIO $ decode <$> BSL.readFile "pingServer.pid" pingClient n them main :: IO () main = getArgs >>= \case [] -> defaultBench [role, host] -> do Right transport <- createTransport defaultZMQParameters (pack host) node <- newLocalNode transport initRemoteTable case role of "SERVER" -> runProcess node initialServer "CLIENT" -> fmap read getLine >>= runProcess node . initialClient _ -> error "Role should be either SERVER or CLIENT" _ -> error "either call benchmark with [SERVER|CLIENT] host or without arguments" where defaultBench = do void . forkOS $ do Right transport <- createTransport defaultZMQParameters "127.0.0.1" node <- newLocalNode transport initRemoteTable runProcess node $ initialServer threadDelay 1000000 e <- newEmptyMVar void . forkOS $ do putStrLn "pings time\n--- ---\n" forM_ [100,200,600,800,1000,2000,5000,8000,10000] $ \i -> do Right transport <- createTransport defaultZMQParameters "127.0.0.1" node <- newLocalNode transport initRemoteTable d <- time_ (runProcess node $ initialClient i) printf "%-8i %10.4f\n" i d putMVar e () takeMVar e