streamly-0.7.2: benchmark/Streamly/Benchmark/Prelude/NestedOps.hs
-- |
-- Module : BenchmarkOps
-- Copyright : (c) 2018 Harendra Kumar
--
-- License : MIT
-- Maintainer : streamly@composewell.com
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Streamly.Benchmark.Prelude.NestedOps where
import Control.Exception (try)
import GHC.Exception (ErrorCall)
import qualified Streamly as S hiding (runStream)
import qualified Streamly.Prelude as S
-------------------------------------------------------------------------------
-- Stream generation and elimination
-------------------------------------------------------------------------------
type Stream m a = S.SerialT m a
{-# INLINE source #-}
source :: (S.MonadAsync m, S.IsStream t) => Int -> Int -> t m Int
source = sourceUnfoldrM
-- Change this to "sourceUnfoldrM value n" for consistency
{-# INLINE sourceUnfoldrM #-}
sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
sourceUnfoldrM n value = S.serially $ S.unfoldrM step n
where
step cnt =
if cnt > n + value
then return Nothing
else return (Just (cnt, cnt + 1))
{-# INLINE sourceUnfoldr #-}
sourceUnfoldr :: (Monad m, S.IsStream t) => Int -> Int -> t m Int
sourceUnfoldr start n = S.unfoldr step start
where
step cnt =
if cnt > start + n
then Nothing
else Just (cnt, cnt + 1)
{-# INLINE runStream #-}
runStream :: Monad m => Stream m a -> m ()
runStream = S.drain
{-# INLINE runToList #-}
runToList :: Monad m => Stream m a -> m [a]
runToList = S.toList
-------------------------------------------------------------------------------
-- Benchmark ops
-------------------------------------------------------------------------------
{-# INLINE toNullAp #-}
toNullAp
:: (S.IsStream t, S.MonadAsync m, Applicative (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
toNullAp linearCount t start = runStream . t $
(+) <$> source start nestedCount2 <*> source start nestedCount2
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE toNull #-}
toNull
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
toNull linearCount t start = runStream . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
return $ x + y
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE toNull3 #-}
toNull3
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
toNull3 linearCount t start = runStream . t $ do
x <- source start nestedCount3
y <- source start nestedCount3
z <- source start nestedCount3
return $ x + y + z
where
nestedCount3 = round (fromIntegral linearCount**(1/3::Double))
{-# INLINE toList #-}
toList
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m [Int]
toList linearCount t start = runToList . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
return $ x + y
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
-- Taking a specified number of elements is very expensive in logict so we have
-- a test to measure the same.
{-# INLINE toListSome #-}
toListSome
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m [Int]
toListSome linearCount t start =
runToList . t $ S.take 10000 $ do
x <- source start nestedCount2
y <- source start nestedCount2
return $ x + y
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE filterAllOut #-}
filterAllOut
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
filterAllOut linearCount t start = runStream . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
let s = x + y
if s < 0
then return s
else S.nil
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE filterAllIn #-}
filterAllIn
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
filterAllIn linearCount t start = runStream . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
let s = x + y
if s > 0
then return s
else S.nil
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE filterSome #-}
filterSome
:: (S.IsStream t, S.MonadAsync m, Monad (t m))
=> Int -> (t m Int -> S.SerialT m Int) -> Int -> m ()
filterSome linearCount t start = runStream . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
let s = x + y
if s > 1100000
then return s
else S.nil
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))
{-# INLINE breakAfterSome #-}
breakAfterSome
:: (S.IsStream t, Monad (t IO))
=> Int -> (t IO Int -> S.SerialT IO Int) -> Int -> IO ()
breakAfterSome linearCount t start = do
(_ :: Either ErrorCall ()) <- try $ runStream . t $ do
x <- source start nestedCount2
y <- source start nestedCount2
let s = x + y
if s > 1100000
then error "break"
else return s
return ()
where
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))