Last active
August 29, 2015 14:13
-
-
Save phadej/ca603306992cee39ce9d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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