streamly/benchmark/Linear.hs
Harendra Kumar 7d577a469b Add detailed benchmarks for folds
INLINE foldlM'
2018-12-29 21:10:02 +05:30

265 lines
11 KiB
Haskell

-- |
-- Module : Main
-- Copyright : (c) 2018 Harendra Kumar
--
-- License : BSD3
-- Maintainer : harendra.kumar@gmail.com
import Control.DeepSeq (NFData)
import Data.Functor.Identity (Identity, runIdentity)
import System.Random (randomRIO)
import qualified GHC.Exts as GHC
import qualified LinearOps as Ops
import Streamly
import qualified Streamly.Prelude as S
import Gauge
-- We need a monadic bind here to make sure that the function f does not get
-- completely optimized out by the compiler in some cases.
-- | Takes a fold method, and uses it with a default source.
{-# INLINE benchIOSink #-}
benchIOSink
:: (IsStream t, NFData b)
=> String -> (t IO Int -> IO b) -> Benchmark
benchIOSink name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
-- XXX We should be using sourceUnfoldrM for fair comparison with IO monad, but
-- we can't use it as it requires MonadAsync constraint.
{-# INLINE benchIdentitySink #-}
benchIdentitySink
:: (IsStream t, NFData b)
=> String -> (t Identity Int -> Identity b) -> Benchmark
benchIdentitySink name f = bench name $ nf (f . Ops.sourceUnfoldr) 1
-- | Takes a source, and uses it with a default drain/fold method.
{-# INLINE benchIOSrc #-}
benchIOSrc
:: (t IO a -> SerialT IO a)
-> String
-> (Int -> t IO a)
-> Benchmark
benchIOSrc t name f =
bench name $ nfIO $ randomRIO (1,1) >>= Ops.toNull t . f
{-# INLINE benchPure #-}
benchPure :: NFData b => String -> (Int -> a) -> (a -> b) -> Benchmark
benchPure name src f = bench name $ nfIO $ randomRIO (1,1) >>= return . f . src
{-# INLINE benchPureSink #-}
benchPureSink :: NFData b => String -> (SerialT Identity Int -> b) -> Benchmark
benchPureSink name f = benchPure name Ops.sourceUnfoldr f
{-# INLINE benchPureSinkIO #-}
benchPureSinkIO
:: NFData b
=> String -> (SerialT Identity Int -> IO b) -> Benchmark
benchPureSinkIO name f =
bench name $ nfIO $ randomRIO (1, 1) >>= f . Ops.sourceUnfoldr
{-# INLINE benchPureSrc #-}
benchPureSrc :: String -> (Int -> SerialT Identity a) -> Benchmark
benchPureSrc name src = benchPure name src (runIdentity . runStream)
main :: IO ()
main =
defaultMain
[ bgroup "serially"
[ bgroup "pure"
[ benchPureSink "id" id
, benchPureSink "eqBy" Ops.eqBy
, benchPureSink "==" Ops.eqInstance
, benchPureSink "/=" Ops.eqInstanceNotEq
, benchPureSink "cmpBy" Ops.cmpBy
, benchPureSink "<" Ops.ordInstance
, benchPureSink "min" Ops.ordInstanceMin
, benchPureSrc "IsList.fromList" Ops.sourceIsList
, benchPureSink "IsList.toList" GHC.toList
, benchPureSrc "IsString.fromString" Ops.sourceIsString
, benchPure "readsPrec" (\n -> S.fromList [1..n :: Int])
Ops.readInstance
, benchPureSink "showsPrec" Ops.showInstance
, benchPure "showsPrecList" (\n -> S.fromList [1..n :: Int])
Ops.showInstanceList
, benchPureSink "foldl'" Ops.pureFoldl'
, benchPureSink "foldable/foldl'" Ops.foldableFoldl'
, benchPureSink "foldable/sum" Ops.foldableSum
, benchPureSinkIO "traversable/mapM" Ops.traversableMapM
]
, bgroup "generation"
[ -- Most basic, barely stream continuations running
benchIOSrc serially "unfoldr" Ops.sourceUnfoldr
, benchIOSrc serially "unfoldrM" Ops.sourceUnfoldrM
, benchIOSrc serially "intFromTo" Ops.sourceIntFromTo
, benchIOSrc serially "intFromThenTo" Ops.sourceIntFromThenTo
, benchIOSrc serially "integerFromStep" Ops.sourceIntegerFromStep
, benchIOSrc serially "fracFromThenTo" Ops.sourceFracFromThenTo
, benchIOSrc serially "fracFromTo" Ops.sourceFracFromTo
, benchIOSrc serially "fromList" Ops.sourceFromList
, benchIOSrc serially "fromListM" Ops.sourceFromListM
-- These are essentially cons and consM
, benchIOSrc serially "fromFoldable" Ops.sourceFromFoldable
, benchIOSrc serially "fromFoldableM" Ops.sourceFromFoldableM
-- These are essentially appends
, benchIOSrc serially "foldMapWith" Ops.sourceFoldMapWith
, benchIOSrc serially "foldMapWithM" Ops.sourceFoldMapWithM
, benchIOSrc serially "foldMapM" Ops.sourceFoldMapM
]
, bgroup "elimination"
[ benchIOSink "toNull" $ Ops.toNull serially
, benchIOSink "uncons" Ops.uncons
, benchIOSink "init" Ops.init
, benchIOSink "tail" Ops.tail
, benchIOSink "nullHeadTail" Ops.nullHeadTail
, benchIOSink "mapM_" Ops.mapM_
, benchIOSink "toList" Ops.toList
, bgroup "reduce"
[ bgroup "IO"
[ benchIOSink "foldr" Ops.foldrReduce
, benchIOSink "foldr1" Ops.foldr1Reduce
, benchIOSink "foldl'" Ops.foldl'Reduce
, benchIOSink "foldl1'" Ops.foldl1'Reduce
, benchIOSink "foldlM'" Ops.foldlM'Reduce
]
, bgroup "Identity"
[ benchIdentitySink "foldr" Ops.foldrReduce
, benchIdentitySink "foldr1" Ops.foldr1Reduce
, benchIdentitySink "foldl'" Ops.foldl'Reduce
, benchIdentitySink "foldl1'" Ops.foldl1'Reduce
, benchIdentitySink "foldlM'" Ops.foldlM'Reduce
]
]
, bgroup "build"
[ bgroup "IO"
[ benchIOSink "foldr" Ops.foldrBuild
, benchIOSink "foldrM" Ops.foldrMBuild
, benchIOSink "foldl'" Ops.foldl'Build
, benchIOSink "foldlM'" Ops.foldlM'Build
]
, bgroup "Identity"
[ benchIdentitySink "foldr" Ops.foldrBuild
, benchIdentitySink "foldrM" Ops.foldrMBuild
, benchIdentitySink "foldl'" Ops.foldl'Build
, benchIdentitySink "foldlM'" Ops.foldlM'Build
]
]
, benchIOSink "last" Ops.last
, benchIOSink "length" Ops.length
, benchIOSink "elem" Ops.elem
, benchIOSink "notElem" Ops.notElem
, benchIOSink "all" Ops.all
, benchIOSink "any" Ops.any
, benchIOSink "and" Ops.and
, benchIOSink "or" Ops.or
, benchIOSink "find" Ops.find
, benchIOSink "findIndex" Ops.findIndex
, benchIOSink "elemIndex" Ops.elemIndex
, benchIOSink "maximum" Ops.maximum
, benchIOSink "maximumBy" Ops.maximumBy
, benchIOSink "minimum" Ops.minimum
, benchIOSink "minimumBy" Ops.minimumBy
, benchIOSink "sum" Ops.sum
, benchIOSink "product" Ops.product
]
, bgroup "transformation"
[ benchIOSink "scan" (Ops.scan 1)
, benchIOSink "scanl1'" (Ops.scanl1' 1)
, benchIOSink "map" (Ops.map 1)
, benchIOSink "fmap" (Ops.fmap 1)
, benchIOSink "mapM" (Ops.mapM serially 1)
, benchIOSink "mapMaybe" (Ops.mapMaybe 1)
, benchIOSink "mapMaybeM" (Ops.mapMaybeM 1)
, bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
Ops.sequence serially (Ops.sourceUnfoldrMAction n)
, benchIOSink "findIndices" (Ops.findIndices 1)
, benchIOSink "elemIndices" (Ops.elemIndices 1)
]
, bgroup "transformationX4"
[ benchIOSink "scan" (Ops.scan 4)
, benchIOSink "scanl1'" (Ops.scanl1' 4)
, benchIOSink "map" (Ops.map 4)
, benchIOSink "fmap" (Ops.fmap 4)
, benchIOSink "mapM" (Ops.mapM serially 4)
, benchIOSink "mapMaybe" (Ops.mapMaybe 4)
, benchIOSink "mapMaybeM" (Ops.mapMaybeM 4)
-- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
-- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
, benchIOSink "findIndices" (Ops.findIndices 4)
, benchIOSink "elemIndices" (Ops.elemIndices 4)
]
, bgroup "filtering"
[ benchIOSink "filter-even" (Ops.filterEven 1)
, benchIOSink "filter-all-out" (Ops.filterAllOut 1)
, benchIOSink "filter-all-in" (Ops.filterAllIn 1)
, benchIOSink "take-all" (Ops.takeAll 1)
, benchIOSink "takeWhile-true" (Ops.takeWhileTrue 1)
--, benchIOSink "takeWhileM-true" (Ops.takeWhileMTrue 1)
, benchIOSink "drop-one" (Ops.dropOne 1)
, benchIOSink "drop-all" (Ops.dropAll 1)
, benchIOSink "dropWhile-true" (Ops.dropWhileTrue 1)
--, benchIOSink "dropWhileM-true" (Ops.dropWhileMTrue 1)
, benchIOSink "dropWhile-false" (Ops.dropWhileFalse 1)
, benchIOSink "deleteBy" (Ops.deleteBy 1)
, benchIOSink "insertBy" (Ops.insertBy 1)
]
, bgroup "filteringX4"
[ benchIOSink "filter-even" (Ops.filterEven 4)
, benchIOSink "filter-all-out" (Ops.filterAllOut 4)
, benchIOSink "filter-all-in" (Ops.filterAllIn 4)
, benchIOSink "take-all" (Ops.takeAll 4)
, benchIOSink "takeWhile-true" (Ops.takeWhileTrue 4)
--, benchIOSink "takeWhileM-true" (Ops.takeWhileMTrue 4)
, benchIOSink "drop-one" (Ops.dropOne 4)
, benchIOSink "drop-all" (Ops.dropAll 4)
, benchIOSink "dropWhile-true" (Ops.dropWhileTrue 4)
--, benchIOSink "dropWhileM-true" (Ops.dropWhileMTrue 4)
, benchIOSink "dropWhile-false" (Ops.dropWhileFalse 4)
, benchIOSink "deleteBy" (Ops.deleteBy 4)
, benchIOSink "insertBy" (Ops.insertBy 4)
]
, bgroup "multi-stream"
[ benchIOSink "eqBy" Ops.eqBy
, benchIOSink "cmpBy" Ops.cmpBy
, benchIOSink "zip" Ops.zip
, benchIOSink "zipM" Ops.zipM
, benchIOSink "mergeBy" Ops.mergeBy
, benchIOSink "isPrefixOf" Ops.isPrefixOf
, benchIOSink "isSubsequenceOf" Ops.isSubsequenceOf
, benchIOSink "stripPrefix" Ops.stripPrefix
, benchIOSrc serially "concatMap" Ops.concatMap
]
, bgroup "mixed"
[ benchIOSink "sum-product-fold" Ops.sumProductFold
, benchIOSink "sum-product-scan" Ops.sumProductScan
]
, bgroup "mixedX4"
[ benchIOSink "scan-map" (Ops.scanMap 4)
, benchIOSink "drop-map" (Ops.dropMap 4)
, benchIOSink "drop-scan" (Ops.dropScan 4)
, benchIOSink "take-drop" (Ops.takeDrop 4)
, benchIOSink "take-scan" (Ops.takeScan 4)
, benchIOSink "take-map" (Ops.takeMap 4)
, benchIOSink "filter-drop" (Ops.filterDrop 4)
, benchIOSink "filter-take" (Ops.filterTake 4)
, benchIOSink "filter-scan" (Ops.filterScan 4)
, benchIOSink "filter-scanl1" (Ops.filterScanl1 4)
, benchIOSink "filter-map" (Ops.filterMap 4)
]
, bgroup "iterated"
[ benchIOSrc serially "mapM" Ops.iterateMapM
, benchIOSrc serially "scan(1/100)" Ops.iterateScan
, benchIOSrc serially "scanl1(1/100)" Ops.iterateScanl1
, benchIOSrc serially "filterEven" Ops.iterateFilterEven
, benchIOSrc serially "takeAll" Ops.iterateTakeAll
, benchIOSrc serially "dropOne" Ops.iterateDropOne
, benchIOSrc serially "dropWhileFalse" Ops.iterateDropWhileFalse
, benchIOSrc serially "dropWhileTrue" Ops.iterateDropWhileTrue
]
]
]