5import Control.Applicative (Alternative(..))
6import Control.Exception (assert)
7import Control.Monad (guard)
8import Criterion.Main (defaultMain, bgroup, bench, nfIO)
10import qualified Asyncly as A
11import qualified Asyncly.Prelude as A
13#ifdef EXTRA_BENCHMARKS
14import Control.Monad.IO.Class (MonadIO (liftIO))
15import Data.Atomics (atomicModifyIORefCAS)
16import Data.IORef (IORef, newIORef, writeIORef)
17import System.IO.Unsafe (unsafePerformIO)
19import qualified Conduit.Simple as S
20import qualified Control.Monad.Logic as LG
21import qualified Data.Machine as M
22#if MIN_VERSION_transient(0,5,1)
23import qualified Transient.Internals as T
24import qualified Transient.Indeterminism as T
26import qualified ListT as LT
31 -- XXX due to a GHC bug passing bind as an argument causes perf
32 -- degradation, so we should keep that in account when comparing.
33 let as = asyncly_basic
36 [ bgroup "serial bind"
37 [ bench "serial" $ nfIO (as (>>=) (A.<>))
38 , bench "fair serial" $ nfIO (as (>>=) (A.<=>))
39 , bench "left parallel" $ nfIO (as (>>=) (A.<|))
40 , bench "fair parallel" $ nfIO (as (>>=) (A.<|>))
44 [ bench "serial" $ nfIO (as (A.>->) (A.<>))
45 , bench "fair serial" $ nfIO (as (A.>->) (A.<=>))
46 , bench "left parallel" $ nfIO (as (A.>->) (A.<|))
47 , bench "fair parallel" $ nfIO (as (A.>->) (A.<|>))
50 , bgroup "parallel bind"
51 [ bench "serial" $ nfIO (as (A.>>|) (A.<>))
52 , bench "fair serial" $ nfIO (as (A.>>|) (A.<=>))
53 , bench "left parallel" $ nfIO (as (A.>>|) (A.<|))
54 , bench "fair parallel" $ nfIO (as (A.>>|) (A.<|>))
57 , bgroup "fair parallel bind"
58 [ bench "serial" $ nfIO (as (A.>|>) (A.<>))
59 , bench "fair serial" $ nfIO (as (A.>|>) (A.<=>))
60 , bench "left parallel" $ nfIO (as (A.>|>) (A.<|))
61 , bench "fair parallel" $ nfIO (as (A.>|>) (A.<|>))
64 -- Benchmark smallest possible actions composed together
65 , bgroup "serial bind nil"
66 [ bench "serial" $ nfIO (asyncly_nil (A.<>))
67 , bench "fair serial" $ nfIO (asyncly_nil (A.<=>))
68 , bench "left parallel" $ nfIO (asyncly_nil (A.<|))
69 , bench "fair parallel" $ nfIO (asyncly_nil (A.<|>))
72#ifdef EXTRA_BENCHMARKS
73#if MIN_VERSION_transient(0,5,1)
75 [ bench "transient" $ nfIO transient_basic
76 , bench "transient-nil" $ nfIO transient_nil
78 , bench "logict" $ nfIO logict_basic
79 , bench "list-t" $ nfIO list_t_basic
80 , bench "simple-conduit" $ nfIO simple_conduit_basic
81 , bench "machines" $ nfIO machines_basic
87map :: Monad m => (a -> Int) -> a -> m Int
90{-# INLINABLE filter #-}
91filter :: (Monad m, Alternative m) => (a -> Bool) -> a -> m a
92filter cond x = guard (not $ cond x) >> return x
94amap :: (Int -> Int) -> Int -> A.AsyncT IO Int
97afilter :: (Int -> Bool) -> Int -> A.AsyncT IO Int
100{-# INLINE asyncly_basic #-}
102 :: (A.AsyncT IO Int -> (Int -> A.AsyncT IO Int) -> A.AsyncT IO Int)
103 -> (A.AsyncT IO Int -> A.AsyncT IO Int -> A.AsyncT IO Int)
105asyncly_basic f g = do
107 A.drop 100 (A.forEachWith g [1..100000 :: Int] $ \x ->
108 afilter even x `f` amap (+1))
110 `f` afilter (\y -> y `mod` 2 == 0)
111 assert (Prelude.length xs == 49900) $
112 return (Prelude.length xs)
114{-# INLINE asyncly_nil #-}
115asyncly_nil :: (A.AsyncT IO Int -> A.AsyncT IO Int -> A.AsyncT IO Int)
119 (A.forEachWith f [1..100000:: Int] $
120 \x -> return x >>= return . id)
121 assert (Prelude.length xs == 100000) $
122 return (Prelude.length xs)
124#ifdef EXTRA_BENCHMARKS
125#if MIN_VERSION_transient(0,5,1)
127{-# NOINLINE count #-}
129count = unsafePerformIO $ newIORef 0
131drop :: (MonadIO m, Alternative m) => Int -> Int -> m Int
134 mn <- liftIO $ atomicModifyIORefCAS count $ \n ->
135 if n < num then (n + 1, False) else (n, True)
139tmap :: (a -> Int) -> a -> T.TransIO Int
142tfilter :: (a -> Bool) -> a -> T.TransIO a
145tdrop :: Int -> Int -> T.TransIO Int
148transient_basic :: IO (Maybe Int)
150transient_basic = T.keep' $ T.threads 0 $ do
151 liftIO $ writeIORef count 0
152 xs <- T.group 49900 $ do
153 T.choose [1..100000 :: Int]
158 >>= tfilter (\x -> x `mod` 2 == 0)
160 assert (Prelude.length xs == 49900) $
161 T.exit (Prelude.length xs)
163transient_nil :: IO (Maybe Int)
164transient_nil = T.keep' $ T.threads 0 $ do
165 xs <- T.group 49900 $ do
166 T.choose [1..100000 :: Int]
167 assert (Prelude.length xs == 49900) $
168 T.exit (Prelude.length xs)
171lfilter :: (Int -> Bool) -> Int -> LT.ListT IO Int
174lmap :: (Int -> Int) -> Int -> LT.ListT IO Int
177ldrop :: Int -> Int -> LT.ListT IO Int
180list_t_basic :: IO Int
184 LT.fromFoldable [1..100000 :: Int]
189 >>= lfilter (\x -> x `mod` 2 == 0)
190 assert (Prelude.length xs == 49900) $
191 return (Prelude.length xs)
193lgfilter :: (Int -> Bool) -> Int -> LG.LogicT IO Int
194lgfilter = Main.filter
196lgmap :: (Int -> Int) -> Int -> LG.LogicT IO Int
199lgdrop :: Int -> Int -> LG.LogicT IO Int
202logict_basic :: IO Int
205 --xs <- LG.observeManyT 2900 $ do
206 xs <- LG.observeAllT $ do
207 LG.msum $ Prelude.map return [1..100000]
212 >>= lgfilter (\x -> x `mod` 2 == 0)
213 assert (Prelude.length xs == 49900) $
214 return (Prelude.length xs)
216simple_conduit_basic :: IO Int
217simple_conduit_basic = do
218 xs <- S.sourceList [1..100000]
220 S.$= S.mapC ((+1) :: Int -> Int)
222 S.$= S.mapC ((+1) :: Int -> Int)
223 S.$= S.filterC (\x -> x `mod` 2 == 0)
225 assert (Prelude.length xs == 49900) $
226 return (Prelude.length (xs :: [Int]))
228machines_basic :: IO Int
230 xs <- M.runT $ M.source [1..100000]
235 M.~> M.filtered (\x -> x `mod` 2 == 0)
236 assert (Prelude.length xs == 49900) $
237 return (Prelude.length (xs ::[Int]))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list