Skip to content

Instantly share code, notes, and snippets.

@phadej
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phadej/ca603306992cee39ce9d to your computer and use it in GitHub Desktop.
Save phadej/ca603306992cee39ce9d to your computer and use it in GitHub Desktop.
bench: queue
version: 0.1.0.0
license-file: LICENSE
author: foo
maintainer: foo@bar.com
build-type: Simple
cabal-version: >=1.10
executable queue
main-is: Main.hs
ghc-options: -threaded
build-depends: base >=4.7 && <4.8, criterion, pipes-concurrency, unagi-chan, stm, pipes
default-language: Haskell2010
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Concurrent (threadDelay)
import Control.Monad (forever)
import Pipes
import qualified Pipes.Concurrent as Pipes
import Control.Applicative
import Control.Monad (replicateM_)
import System.Environment (getArgs)
import Control.Concurrent.Chan
import Control.Concurrent (forkIO)
import qualified Control.Concurrent.Chan.Unagi as U
import Control.Concurrent.STM
import Control.Concurrent.MVar
import Criterion.Main
data Event = Msg String | Status | Quit deriving (Show)
----------------------------------------------------------------------
-- Pipes
----------------------------------------------------------------------
pipesLogMsg = yield (Msg "hello")
pipesManyLogs num = replicateM_ num pipesLogMsg
pipesAddProducer num o = Pipes.forkIO $ do runEffect $ (pipesManyLogs num) >-> Pipes.toOutput o
Pipes.performGC
pipesHandler max = loop 0
where
loop mnum = do
if mnum == max
then lift $ pure ()
else do event <- await
case event of
Msg _ -> loop (mnum + 1)
Status -> (lift $ putStrLn (show mnum)) *> loop mnum
Quit -> return ()
----------------------------------------------------------------------
-- Chan
----------------------------------------------------------------------
chanAddProducer num ch = forkIO $ chanManyLogs num ch
chanManyLogs num ch = replicateM_ num (writeChan ch (Msg "hello"))
chanHandler ch max = handlerIO (readChan ch) max
----------------------------------------------------------------------
-- TChan
----------------------------------------------------------------------
tchanAddProducer num ch = forkIO $ atomically $ tchanManyLogs num ch
tchanManyLogs num ch = replicateM_ num (writeTChan ch (Msg "hello"))
tchanHandler ch max = handlerIO (atomically $ readTChan ch) max
----------------------------------------------------------------------
-- Unagi-Chan
----------------------------------------------------------------------
uchanAddProducer num ch = forkIO $ uchanManyLogs num ch
uchanManyLogs num ch = replicateM_ num (U.writeChan ch (Msg "hello"))
uchanHandler ch max = handlerIO (U.readChan ch) max
----------------------------------------------------------------------
-- MVars
----------------------------------------------------------------------
mvarAddProducer num m = forkIO $ mvarManyLogs num m
mvarManyLogs num m = replicateM_ num (putMVar m (Msg "hello"))
mvarHandler m max = handlerIO (takeMVar m) max
----------------------------------------------------------------------
-- Utils
----------------------------------------------------------------------
handlerIO f max = loop 0 where
loop mnum = do
if mnum == max
then pure ()
else do event <- f
case event of
Msg _ -> loop (mnum + 1)
Status -> putStrLn (show mnum) *> loop mnum
Quit -> return ()
----------------------------------------------------------------------
-- Main
----------------------------------------------------------------------
main = defaultMain [
bench "pipes" $ nfIO $ do
(output, input) <- Pipes.spawn Pipes.Unbounded
replicateM_ prodNum (pipesAddProducer msgNum output)
runEffect $ Pipes.fromInput input >-> pipesHandler totalMsg
, bench "Chan" $ nfIO $ do
ch <- newChan
replicateM_ prodNum (chanAddProducer msgNum ch)
chanHandler ch totalMsg
, bench "TChan" $ nfIO $ do
ch <- newTChanIO
replicateM_ prodNum (tchanAddProducer msgNum ch)
tchanHandler ch totalMsg
, bench "Unagi-Chan" $ nfIO $ do
(inCh, outCh) <- U.newChan
replicateM_ prodNum (uchanAddProducer msgNum inCh)
uchanHandler outCh totalMsg
, bench "MVar" $ nfIO $ do
m <- newEmptyMVar
replicateM_ prodNum (mvarAddProducer msgNum m)
mvarHandler m totalMsg
]
where
prodNum = 20
msgNum = 1000
totalMsg = msgNum * prodNum
# Multiple threads (I have 4 cores)
% dist/build/bench/bench +RTS -N4
benchmarking pipes
time 91.37 ms (89.46 ms .. 93.03 ms)
0.999 R² (0.999 R² .. 1.000 R²)
mean 92.62 ms (91.67 ms .. 93.42 ms)
std dev 1.239 ms (772.8 μs .. 1.738 ms)
benchmarking Chan
time 95.22 ms (81.40 ms .. 107.0 ms)
0.978 R² (0.956 R² .. 0.997 R²)
mean 94.44 ms (87.04 ms .. 101.6 ms)
std dev 11.11 ms (6.237 ms .. 17.10 ms)
variance introduced by outliers: 32% (moderately inflated)
benchmarking TChan
time 38.38 ms (36.83 ms .. 40.30 ms)
0.992 R² (0.983 R² .. 0.999 R²)
mean 38.32 ms (37.62 ms .. 39.33 ms)
std dev 1.775 ms (1.260 ms .. 2.568 ms)
variance introduced by outliers: 12% (moderately inflated)
benchmarking Unagi-Chan
time 2.117 ms (2.024 ms .. 2.268 ms)
0.982 R² (0.966 R² .. 0.998 R²)
mean 2.148 ms (2.103 ms .. 2.222 ms)
std dev 185.5 μs (90.22 μs .. 309.2 μs)
variance introduced by outliers: 61% (severely inflated)
benchmarking MVar
time 112.2 ms (72.60 ms .. 139.9 ms)
0.878 R² (0.664 R² .. 0.990 R²)
mean 105.4 ms (91.38 ms .. 117.6 ms)
std dev 20.03 ms (15.54 ms .. 25.26 ms)
variance introduced by outliers: 65% (severely inflated)
# Single thread
% ./dist/build/bench/bench
benchmarking pipes
time 66.00 ms (55.80 ms .. 71.85 ms)
0.970 R² (0.913 R² .. 0.999 R²)
mean 70.76 ms (67.03 ms .. 80.06 ms)
std dev 9.777 ms (3.090 ms .. 16.27 ms)
variance introduced by outliers: 44% (moderately inflated)
benchmarking Chan
time 59.65 ms (44.31 ms .. 81.80 ms)
0.789 R² (0.642 R² .. 0.923 R²)
mean 59.17 ms (52.23 ms .. 67.39 ms)
std dev 13.16 ms (9.295 ms .. 19.62 ms)
variance introduced by outliers: 75% (severely inflated)
benchmarking TChan
time 32.07 ms (30.25 ms .. 33.65 ms)
0.991 R² (0.981 R² .. 0.997 R²)
mean 32.27 ms (31.45 ms .. 33.61 ms)
std dev 2.158 ms (1.310 ms .. 3.279 ms)
variance introduced by outliers: 22% (moderately inflated)
benchmarking Unagi-Chan
time 1.917 ms (1.806 ms .. 2.033 ms)
0.977 R² (0.967 R² .. 0.989 R²)
mean 2.010 ms (1.931 ms .. 2.128 ms)
std dev 308.6 μs (205.9 μs .. 454.1 μs)
variance introduced by outliers: 84% (severely inflated)
benchmarking MVar
time 10.58 ms (10.05 ms .. 11.06 ms)
0.984 R² (0.962 R² .. 0.995 R²)
mean 11.80 ms (11.48 ms .. 12.18 ms)
std dev 988.4 μs (805.4 μs .. 1.227 ms)
variance introduced by outliers: 45% (moderately inflated)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment