mirror of
https://github.com/composewell/streamly.git
synced 2024-09-20 07:58:27 +03:00
Move and split benchmarks from O_1_Space.hs to Groups.hs
* Streamly/Benchmark/Prelude/O_1_Space.hs -> lib/Streamly/Benchmark/Groups.hs * Modify O_1_Space.hs accordingly
This commit is contained in:
parent
e754561195
commit
2dacf99488
@ -5,80 +5,10 @@
|
||||
-- License : BSD3
|
||||
-- Maintainer : streamly@composewell.com
|
||||
|
||||
import Control.DeepSeq (NFData(..))
|
||||
import Data.Functor.Identity (Identity, runIdentity)
|
||||
import Data.Monoid (Last(..))
|
||||
import System.Random (randomRIO)
|
||||
|
||||
import qualified GHC.Exts as GHC
|
||||
import qualified Streamly.Benchmark.Prelude as Ops
|
||||
|
||||
import Streamly
|
||||
import qualified Streamly.Data.Fold as FL
|
||||
import qualified Streamly.Prelude as S
|
||||
import qualified Streamly.Internal.Data.Sink as Sink
|
||||
|
||||
import Streamly.Internal.Data.Time.Units
|
||||
import qualified Streamly.Internal.Memory.Array as IA
|
||||
import qualified Streamly.Internal.Data.Fold as IFL
|
||||
import qualified Streamly.Internal.Prelude as IP
|
||||
import qualified Streamly.Internal.Data.Pipe as Pipe
|
||||
|
||||
import qualified NestedOps as Nested
|
||||
import qualified NestedUnfoldOps as NestedUnfold
|
||||
import Streamly.Benchmark.Common
|
||||
import Streamly.Benchmark.Groups
|
||||
|
||||
import Gauge
|
||||
import Streamly.Benchmark.Common
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- 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)
|
||||
=> Int -> String -> (t IO Int -> IO b) -> Benchmark
|
||||
benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source value
|
||||
|
||||
{-# INLINE benchHoistSink #-}
|
||||
benchHoistSink
|
||||
:: (IsStream t, NFData b)
|
||||
=> Int -> String -> (t Identity Int -> IO b) -> Benchmark
|
||||
benchHoistSink value name f =
|
||||
bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.sourceUnfoldr value
|
||||
|
||||
-- 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)
|
||||
=> Int -> String -> (t Identity Int -> Identity b) -> Benchmark
|
||||
benchIdentitySink value name f = bench name $ nf (f . Ops.sourceUnfoldr value) 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 benchPureSink #-}
|
||||
benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
|
||||
benchPureSink value name f = benchPure name (Ops.sourceUnfoldr value) f
|
||||
|
||||
benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
|
||||
benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- In addition to gauge options, the number of elements in the stream can be
|
||||
-- passed using the --stream-size option.
|
||||
@ -86,388 +16,42 @@ benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
|
||||
main :: IO ()
|
||||
main = do
|
||||
(value, cfg, benches) <- parseCLIOpts defaultStreamSize
|
||||
value `seq` runMode (mode cfg) cfg benches
|
||||
[ bgroup "serially"
|
||||
[ bgroup "pure"
|
||||
[ benchPureSink value "id" id
|
||||
, benchPureSink1 "eqBy" (Ops.eqByPure value)
|
||||
, benchPureSink value "==" Ops.eqInstance
|
||||
, benchPureSink value "/=" Ops.eqInstanceNotEq
|
||||
, benchPureSink1 "cmpBy" (Ops.cmpByPure value)
|
||||
, benchPureSink value "<" Ops.ordInstance
|
||||
, benchPureSink value "min" Ops.ordInstanceMin
|
||||
, benchPureSrc "IsList.fromList" (Ops.sourceIsList value)
|
||||
-- length is used to check for foldr/build fusion
|
||||
, benchPureSink value "length . IsList.toList" (length . GHC.toList)
|
||||
, benchPureSrc "IsString.fromString" (Ops.sourceIsString value)
|
||||
, benchPureSink value "showsPrec pure streams" Ops.showInstance
|
||||
, benchPureSink value "foldl'" Ops.pureFoldl'
|
||||
value `seq`
|
||||
runMode
|
||||
(mode cfg)
|
||||
cfg
|
||||
benches
|
||||
(concat [serial value, wSerial value, zipSerial value])
|
||||
where
|
||||
serial value =
|
||||
concat
|
||||
[ o_1_space_serial_pure value
|
||||
, o_1_space_serial_foldable value
|
||||
, o_1_space_serial_generation value
|
||||
, o_1_space_serial_elimination value
|
||||
, o_1_space_serial_folds value
|
||||
, o_1_space_serial_foldMultiStream value
|
||||
, o_1_space_serial_foldsTransforms value
|
||||
, o_1_space_serial_foldsCompositions value
|
||||
, o_1_space_serial_pipes value
|
||||
, o_1_space_serial_pipesX4 value
|
||||
, o_1_space_serial_transformer value
|
||||
, o_1_space_serial_transformation value
|
||||
, o_1_space_serial_transformationX4 value
|
||||
, o_1_space_serial_filtering value
|
||||
, o_1_space_serial_filteringX4 value
|
||||
, o_1_space_serial_joining value
|
||||
, o_1_space_serial_concatFoldable value
|
||||
, o_1_space_serial_concatSerial value
|
||||
, o_1_space_serial_outerProductStreams value
|
||||
, o_1_space_serial_outerProductUnfolds value
|
||||
, o_1_space_serial_mixed value
|
||||
, o_1_space_serial_mixedX4 value
|
||||
]
|
||||
, bgroup "foldable"
|
||||
[ -- Foldable instance
|
||||
-- type class operations
|
||||
bench "foldl'" $ nf (Ops.foldableFoldl' value) 1
|
||||
, bench "foldrElem" $ nf (Ops.foldableFoldrElem value) 1
|
||||
-- , bench "null" $ nf (Ops.foldableNull value) 1
|
||||
, bench "elem" $ nf (Ops.foldableElem value) 1
|
||||
, bench "length" $ nf (Ops.foldableLength value) 1
|
||||
, bench "sum" $ nf (Ops.foldableSum value) 1
|
||||
, bench "product" $ nf (Ops.foldableProduct value) 1
|
||||
, bench "minimum" $ nf (Ops.foldableMin value) 1
|
||||
, bench "maximum" $ nf (Ops.foldableMax value) 1
|
||||
, bench "length . toList" $
|
||||
nf (length . Ops.foldableToList value) 1
|
||||
|
||||
-- folds
|
||||
, bench "notElem" $ nf (Ops.foldableNotElem value) 1
|
||||
, bench "find" $ nf (Ops.foldableFind value) 1
|
||||
, bench "all" $ nf (Ops.foldableAll value) 1
|
||||
, bench "any" $ nf (Ops.foldableAny value) 1
|
||||
, bench "and" $ nf (Ops.foldableAnd value) 1
|
||||
, bench "or" $ nf (Ops.foldableOr value) 1
|
||||
|
||||
-- Note: minimumBy/maximumBy do not work in constant memory they are in
|
||||
-- the O(n) group of benchmarks down below in this file.
|
||||
|
||||
-- Applicative and Traversable operations
|
||||
-- TBD: traverse_
|
||||
, benchIOSink1 "mapM_" (Ops.foldableMapM_ value)
|
||||
-- TBD: for_
|
||||
-- TBD: forM_
|
||||
, benchIOSink1 "sequence_" (Ops.foldableSequence_ value)
|
||||
-- TBD: sequenceA_
|
||||
-- TBD: asum
|
||||
-- , benchIOSink1 "msum" (Ops.foldableMsum value)
|
||||
wSerial value =
|
||||
concat
|
||||
[ o_1_space_wSerial_transformation value
|
||||
, o_1_space_wSerial_concatMap value
|
||||
, o_1_space_wSerial_outerProduct value
|
||||
]
|
||||
, bgroup "generation"
|
||||
[ -- Most basic, barely stream continuations running
|
||||
benchIOSrc serially "unfoldr" (Ops.sourceUnfoldr value)
|
||||
, benchIOSrc serially "unfoldrM" (Ops.sourceUnfoldrM value)
|
||||
, benchIOSrc serially "intFromTo" (Ops.sourceIntFromTo value)
|
||||
, benchIOSrc serially "intFromThenTo" (Ops.sourceIntFromThenTo value)
|
||||
, benchIOSrc serially "integerFromStep" (Ops.sourceIntegerFromStep value)
|
||||
, benchIOSrc serially "fracFromThenTo" (Ops.sourceFracFromThenTo value)
|
||||
, benchIOSrc serially "fracFromTo" (Ops.sourceFracFromTo value)
|
||||
, benchIOSrc serially "fromList" (Ops.sourceFromList value)
|
||||
, benchIOSrc serially "fromListM" (Ops.sourceFromListM value)
|
||||
-- These are essentially cons and consM
|
||||
, benchIOSrc serially "fromFoldable" (Ops.sourceFromFoldable value)
|
||||
, benchIOSrc serially "fromFoldableM" (Ops.sourceFromFoldableM value)
|
||||
, benchIOSrc serially "currentTime/0.00001s"
|
||||
$ Ops.currentTime value 0.00001
|
||||
]
|
||||
, bgroup "elimination"
|
||||
[ bgroup "reduce"
|
||||
[ bgroup "IO"
|
||||
[
|
||||
benchIOSink value "foldl'" Ops.foldl'Reduce
|
||||
, benchIOSink value "foldl1'" Ops.foldl1'Reduce
|
||||
, benchIOSink value "foldlM'" Ops.foldlM'Reduce
|
||||
]
|
||||
, bgroup "Identity"
|
||||
[
|
||||
benchIdentitySink value "foldl'" Ops.foldl'Reduce
|
||||
, benchIdentitySink value "foldl1'" Ops.foldl1'Reduce
|
||||
, benchIdentitySink value "foldlM'" Ops.foldlM'Reduce
|
||||
]
|
||||
]
|
||||
|
||||
, bgroup "build"
|
||||
[ bgroup "IO"
|
||||
[ benchIOSink value "foldrMElem" (Ops.foldrMElem value)
|
||||
]
|
||||
, bgroup "Identity"
|
||||
[ benchIdentitySink value "foldrMElem" (Ops.foldrMElem value)
|
||||
, benchIdentitySink value "foldrMToStreamLength"
|
||||
(S.length . runIdentity . Ops.foldrMToStream)
|
||||
, benchPureSink value "foldrMToListLength"
|
||||
(length . runIdentity . Ops.foldrMBuild)
|
||||
]
|
||||
]
|
||||
, benchIOSink value "uncons" Ops.uncons
|
||||
, benchIOSink value "toNull" $ Ops.toNull serially
|
||||
, benchIOSink value "mapM_" Ops.mapM_
|
||||
|
||||
, benchIOSink value "init" Ops.init
|
||||
|
||||
-- this is too low and causes all benchmarks reported in ns
|
||||
-- , benchIOSink value "head" Ops.head
|
||||
, benchIOSink value "last" Ops.last
|
||||
-- , benchIOSink value "lookup" Ops.lookup
|
||||
, benchIOSink value "find" (Ops.find value)
|
||||
, benchIOSink value "findIndex" (Ops.findIndex value)
|
||||
, benchIOSink value "elemIndex" (Ops.elemIndex value)
|
||||
|
||||
-- this is too low and causes all benchmarks reported in ns
|
||||
-- , benchIOSink value "null" Ops.null
|
||||
, benchIOSink value "elem" (Ops.elem value)
|
||||
, benchIOSink value "notElem" (Ops.notElem value)
|
||||
, benchIOSink value "all" (Ops.all value)
|
||||
, benchIOSink value "any" (Ops.any value)
|
||||
, benchIOSink value "and" (Ops.and value)
|
||||
, benchIOSink value "or" (Ops.or value)
|
||||
|
||||
, benchIOSink value "length" Ops.length
|
||||
, benchHoistSink value "length . generally" (Ops.length . IP.generally)
|
||||
, benchIOSink value "sum" Ops.sum
|
||||
, benchIOSink value "product" Ops.product
|
||||
|
||||
, benchIOSink value "maximumBy" Ops.maximumBy
|
||||
, benchIOSink value "maximum" Ops.maximum
|
||||
, benchIOSink value "minimumBy" Ops.minimumBy
|
||||
, benchIOSink value "minimum" Ops.minimum
|
||||
|
||||
]
|
||||
, bgroup "folds"
|
||||
[ benchIOSink value "drain" (S.fold FL.drain)
|
||||
, benchIOSink value "drainN" (S.fold (IFL.drainN value))
|
||||
, benchIOSink value "drainWhileTrue" (S.fold (IFL.drainWhile $ (<=) (value + 1)))
|
||||
, benchIOSink value "drainWhileFalse" (S.fold (IFL.drainWhile $ (>=) (value + 1)))
|
||||
, benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
|
||||
, benchIOSink value "last" (S.fold FL.last)
|
||||
, benchIOSink value "lastN.1" (S.fold (IA.lastN 1))
|
||||
, benchIOSink value "lastN.10" (S.fold (IA.lastN 10))
|
||||
, benchIOSink value "length" (S.fold FL.length)
|
||||
, benchIOSink value "sum" (S.fold FL.sum)
|
||||
, benchIOSink value "product" (S.fold FL.product)
|
||||
, benchIOSink value "maximumBy" (S.fold (FL.maximumBy compare))
|
||||
, benchIOSink value "maximum" (S.fold FL.maximum)
|
||||
, benchIOSink value "minimumBy" (S.fold (FL.minimumBy compare))
|
||||
, benchIOSink value "minimum" (S.fold FL.minimum)
|
||||
, benchIOSink value "mean" (\s -> S.fold FL.mean (S.map (fromIntegral :: Int -> Double) s))
|
||||
, benchIOSink value "variance" (\s -> S.fold FL.variance (S.map (fromIntegral :: Int -> Double) s))
|
||||
, benchIOSink value "stdDev" (\s -> S.fold FL.stdDev (S.map (fromIntegral :: Int -> Double) s))
|
||||
|
||||
, benchIOSink value "mconcat" (S.fold FL.mconcat . (S.map (Last . Just)))
|
||||
, benchIOSink value "foldMap" (S.fold (FL.foldMap (Last . Just)))
|
||||
|
||||
, benchIOSink value "index" (S.fold (FL.index (value + 1)))
|
||||
, benchIOSink value "head" (S.fold FL.head)
|
||||
, benchIOSink value "find" (S.fold (FL.find (== (value + 1))))
|
||||
, benchIOSink value "findIndex" (S.fold (FL.findIndex (== (value + 1))))
|
||||
, benchIOSink value "elemIndex" (S.fold (FL.elemIndex (value + 1)))
|
||||
|
||||
, benchIOSink value "null" (S.fold FL.null)
|
||||
, benchIOSink value "elem" (S.fold (FL.elem (value + 1)))
|
||||
, benchIOSink value "notElem" (S.fold (FL.notElem (value + 1)))
|
||||
, benchIOSink value "all" (S.fold (FL.all (<= (value + 1))))
|
||||
, benchIOSink value "any" (S.fold (FL.any (> (value + 1))))
|
||||
, benchIOSink value "and" (\s -> S.fold FL.and (S.map (<= (value + 1)) s))
|
||||
, benchIOSink value "or" (\s -> S.fold FL.or (S.map (> (value + 1)) s))
|
||||
]
|
||||
, bgroup "fold-multi-stream"
|
||||
[ benchIOSink1 "eqBy" (Ops.eqBy value)
|
||||
, benchIOSink1 "cmpBy" (Ops.cmpBy value)
|
||||
, benchIOSink value "isPrefixOf" Ops.isPrefixOf
|
||||
, benchIOSink value "isSubsequenceOf" Ops.isSubsequenceOf
|
||||
, benchIOSink value "stripPrefix" Ops.stripPrefix
|
||||
]
|
||||
, bgroup "folds-transforms"
|
||||
[ benchIOSink value "drain" (S.fold FL.drain)
|
||||
, benchIOSink value "lmap" (S.fold (IFL.lmap (+1) FL.drain))
|
||||
, benchIOSink value "pipe-mapM"
|
||||
(S.fold (IFL.transform (Pipe.mapM (\x -> return $ x + 1)) FL.drain))
|
||||
]
|
||||
, bgroup "folds-compositions" -- Applicative
|
||||
[
|
||||
benchIOSink value "all,any" (S.fold ((,) <$> FL.all (<= (value + 1))
|
||||
<*> FL.any (> (value + 1))))
|
||||
, benchIOSink value "sum,length" (S.fold ((,) <$> FL.sum <*> FL.length))
|
||||
]
|
||||
, bgroup "pipes"
|
||||
[ benchIOSink value "mapM" (Ops.transformMapM serially 1)
|
||||
, benchIOSink value "compose" (Ops.transformComposeMapM serially 1)
|
||||
, benchIOSink value "tee" (Ops.transformTeeMapM serially 1)
|
||||
, benchIOSink value "zip" (Ops.transformZipMapM serially 1)
|
||||
]
|
||||
, bgroup "pipesX4"
|
||||
[ benchIOSink value "mapM" (Ops.transformMapM serially 4)
|
||||
, benchIOSink value "compose" (Ops.transformComposeMapM serially 4)
|
||||
, benchIOSink value "tee" (Ops.transformTeeMapM serially 4)
|
||||
, benchIOSink value "zip" (Ops.transformZipMapM serially 4)
|
||||
]
|
||||
, bgroup "transformer"
|
||||
[ benchIOSrc serially "evalState" (Ops.evalStateT value)
|
||||
, benchIOSrc serially "withState" (Ops.withState value)
|
||||
]
|
||||
, bgroup "transformation"
|
||||
[ benchIOSink value "scanl" (Ops.scan 1)
|
||||
, benchIOSink value "scanl1'" (Ops.scanl1' 1)
|
||||
, benchIOSink value "map" (Ops.map 1)
|
||||
, benchIOSink value "fmap" (Ops.fmap 1)
|
||||
, benchIOSink value "mapM" (Ops.mapM serially 1)
|
||||
, benchIOSink value "mapMaybe" (Ops.mapMaybe 1)
|
||||
, benchIOSink value "mapMaybeM" (Ops.mapMaybeM 1)
|
||||
, bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
|
||||
Ops.sequence serially (Ops.sourceUnfoldrMAction value n)
|
||||
, benchIOSink value "findIndices" (Ops.findIndices value 1)
|
||||
, benchIOSink value "elemIndices" (Ops.elemIndices value 1)
|
||||
, benchIOSink value "foldrS" (Ops.foldrS 1)
|
||||
, benchIOSink value "foldrSMap" (Ops.foldrSMap 1)
|
||||
, benchIOSink value "foldrT" (Ops.foldrT 1)
|
||||
, benchIOSink value "foldrTMap" (Ops.foldrTMap 1)
|
||||
, benchIOSink value "tap" (Ops.tap 1)
|
||||
, benchIOSink value "tapRate 1 second" (Ops.tapRate 1)
|
||||
, benchIOSink value "pollCounts 1 second" (Ops.pollCounts 1)
|
||||
, benchIOSink value "tapAsync" (Ops.tapAsync 1)
|
||||
, benchIOSink value "tapAsyncS" (Ops.tapAsyncS 1)
|
||||
]
|
||||
, bgroup "transformationX4"
|
||||
[ benchIOSink value "scan" (Ops.scan 4)
|
||||
, benchIOSink value "scanl1'" (Ops.scanl1' 4)
|
||||
, benchIOSink value "map" (Ops.map 4)
|
||||
, benchIOSink value "fmap" (Ops.fmap 4)
|
||||
, benchIOSink value "mapM" (Ops.mapM serially 4)
|
||||
, benchIOSink value "mapMaybe" (Ops.mapMaybe 4)
|
||||
, benchIOSink value "mapMaybeM" (Ops.mapMaybeM 4)
|
||||
-- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
|
||||
-- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
|
||||
, benchIOSink value "findIndices" (Ops.findIndices value 4)
|
||||
, benchIOSink value "elemIndices" (Ops.elemIndices value 4)
|
||||
]
|
||||
, bgroup "filtering"
|
||||
[ benchIOSink value "filter-even" (Ops.filterEven 1)
|
||||
, benchIOSink value "filter-all-out" (Ops.filterAllOut value 1)
|
||||
, benchIOSink value "filter-all-in" (Ops.filterAllIn value 1)
|
||||
|
||||
, benchIOSink value "take-all" (Ops.takeAll value 1)
|
||||
, benchIOSink value "takeByTime-all"
|
||||
(Ops.takeByTime (NanoSecond64 maxBound) 1)
|
||||
, benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 1)
|
||||
--, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 1)
|
||||
|
||||
-- "drop-one" is dual to "last"
|
||||
, benchIOSink value "drop-one" (Ops.dropOne 1)
|
||||
, benchIOSink value "drop-all" (Ops.dropAll value 1)
|
||||
, benchIOSink value "dropByTime-all"
|
||||
(Ops.dropByTime (NanoSecond64 maxBound) 1)
|
||||
, benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 1)
|
||||
--, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 1)
|
||||
, benchIOSink value "dropWhile-false" (Ops.dropWhileFalse value 1)
|
||||
|
||||
, benchIOSink value "deleteBy" (Ops.deleteBy value 1)
|
||||
, benchIOSink value "intersperse" (Ops.intersperse value 1)
|
||||
, benchIOSink value "insertBy" (Ops.insertBy value 1)
|
||||
]
|
||||
, bgroup "filteringX4"
|
||||
[ benchIOSink value "filter-even" (Ops.filterEven 4)
|
||||
, benchIOSink value "filter-all-out" (Ops.filterAllOut value 4)
|
||||
, benchIOSink value "filter-all-in" (Ops.filterAllIn value 4)
|
||||
, benchIOSink value "take-all" (Ops.takeAll value 4)
|
||||
, benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 4)
|
||||
--, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 4)
|
||||
, benchIOSink value "drop-one" (Ops.dropOne 4)
|
||||
, benchIOSink value "drop-all" (Ops.dropAll value 4)
|
||||
, benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 4)
|
||||
--, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 4)
|
||||
, benchIOSink value "dropWhile-false" (Ops.dropWhileFalse value 4)
|
||||
, benchIOSink value "deleteBy" (Ops.deleteBy value 4)
|
||||
, benchIOSink value "intersperse" (Ops.intersperse value 4)
|
||||
, benchIOSink value "insertBy" (Ops.insertBy value 4)
|
||||
]
|
||||
, bgroup "joining"
|
||||
[ benchIOSrc1 "zip (2,x/2)" (Ops.zip (value `div` 2))
|
||||
, benchIOSrc1 "zipM (2,x/2)" (Ops.zipM (value `div` 2))
|
||||
, benchIOSrc1 "mergeBy (2,x/2)" (Ops.mergeBy (value `div` 2))
|
||||
, benchIOSrc1 "serial (2,x/2)" (Ops.serial2 (value `div` 2))
|
||||
, benchIOSrc1 "append (2,x/2)" (Ops.append2 (value `div` 2))
|
||||
, benchIOSrc1 "serial (2,2,x/4)" (Ops.serial4 (value `div` 4))
|
||||
, benchIOSrc1 "append (2,2,x/4)" (Ops.append4 (value `div` 4))
|
||||
, benchIOSrc1 "wSerial (2,x/2)" (Ops.wSerial2 value)
|
||||
, benchIOSrc1 "interleave (2,x/2)" (Ops.interleave2 value)
|
||||
, benchIOSrc1 "roundRobin (2,x/2)" (Ops.roundRobin2 value)
|
||||
]
|
||||
, bgroup "concat-foldable"
|
||||
[ benchIOSrc serially "foldMapWith" (Ops.sourceFoldMapWith value)
|
||||
, benchIOSrc serially "foldMapWithM" (Ops.sourceFoldMapWithM value)
|
||||
, benchIOSrc serially "foldMapM" (Ops.sourceFoldMapM value)
|
||||
, benchIOSrc serially "foldWithConcatMapId" (Ops.sourceConcatMapId value)
|
||||
]
|
||||
, bgroup "concat-serial"
|
||||
[ benchIOSrc1 "concatMapPure (2,x/2)" (Ops.concatMapPure 2 (value `div` 2))
|
||||
, benchIOSrc1 "concatMap (2,x/2)" (Ops.concatMap 2 (value `div` 2))
|
||||
, benchIOSrc1 "concatMap (x/2,2)" (Ops.concatMap (value `div` 2) 2)
|
||||
, benchIOSrc1 "concatMapRepl (x/4,4)" (Ops.concatMapRepl4xN value)
|
||||
, benchIOSrc1 "concatUnfoldRepl (x/4,4)" (Ops.concatUnfoldRepl4xN value)
|
||||
|
||||
, benchIOSrc1 "concatMapWithSerial (2,x/2)"
|
||||
(Ops.concatMapWithSerial 2 (value `div` 2))
|
||||
, benchIOSrc1 "concatMapWithSerial (x/2,2)"
|
||||
(Ops.concatMapWithSerial (value `div` 2) 2)
|
||||
|
||||
, benchIOSrc1 "concatMapWithAppend (2,x/2)"
|
||||
(Ops.concatMapWithAppend 2 (value `div` 2))
|
||||
]
|
||||
, bgroup "outer-product-streams"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value serially
|
||||
, benchIO "toNull" $ Nested.toNull value serially
|
||||
, benchIO "toNull3" $ Nested.toNull3 value serially
|
||||
, benchIO "filterAllOut" $ Nested.filterAllOut value serially
|
||||
, benchIO "filterAllIn" $ Nested.filterAllIn value serially
|
||||
, benchIO "filterSome" $ Nested.filterSome value serially
|
||||
, benchIO "breakAfterSome" $ Nested.breakAfterSome value serially
|
||||
]
|
||||
, bgroup "outer-product-unfolds"
|
||||
[ benchIO "toNull" $ NestedUnfold.toNull value
|
||||
, benchIO "toNull3" $ NestedUnfold.toNull3 value
|
||||
, benchIO "concat" $ NestedUnfold.concat value
|
||||
, benchIO "filterAllOut" $ NestedUnfold.filterAllOut value
|
||||
, benchIO "filterAllIn" $ NestedUnfold.filterAllIn value
|
||||
, benchIO "filterSome" $ NestedUnfold.filterSome value
|
||||
, benchIO "breakAfterSome" $ NestedUnfold.breakAfterSome value
|
||||
]
|
||||
-- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
|
||||
-- library. If scan/fold followed by a map is efficient enough we may not
|
||||
-- need monolithic implementations of these.
|
||||
, bgroup "mixed"
|
||||
[ benchIOSink value "scanl-map" (Ops.scanMap 1)
|
||||
, benchIOSink value "foldl-map" Ops.foldl'ReduceMap
|
||||
, benchIOSink value "sum-product-fold" Ops.sumProductFold
|
||||
, benchIOSink value "sum-product-scan" Ops.sumProductScan
|
||||
]
|
||||
, bgroup "mixedX4"
|
||||
[ benchIOSink value "scan-map" (Ops.scanMap 4)
|
||||
, benchIOSink value "drop-map" (Ops.dropMap 4)
|
||||
, benchIOSink value "drop-scan" (Ops.dropScan 4)
|
||||
, benchIOSink value "take-drop" (Ops.takeDrop value 4)
|
||||
, benchIOSink value "take-scan" (Ops.takeScan value 4)
|
||||
, benchIOSink value "take-map" (Ops.takeMap value 4)
|
||||
, benchIOSink value "filter-drop" (Ops.filterDrop value 4)
|
||||
, benchIOSink value "filter-take" (Ops.filterTake value 4)
|
||||
, benchIOSink value "filter-scan" (Ops.filterScan 4)
|
||||
, benchIOSink value "filter-scanl1" (Ops.filterScanl1 4)
|
||||
, benchIOSink value "filter-map" (Ops.filterMap value 4)
|
||||
]
|
||||
]
|
||||
, bgroup "wSerially"
|
||||
[ bgroup "transformation"
|
||||
[ benchIOSink value "fmap" $ Ops.fmap' wSerially 1
|
||||
]
|
||||
, bgroup "concatMap"
|
||||
[ benchIOSrc1 "concatMapWithWSerial (2,x/2)"
|
||||
(Ops.concatMapWithWSerial 2 (value `div` 2))
|
||||
, benchIOSrc1 "concatMapWithWSerial (x/2,2)"
|
||||
(Ops.concatMapWithWSerial (value `div` 2) 2)
|
||||
]
|
||||
, bgroup "outer-product"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value wSerially
|
||||
, benchIO "toNull" $ Nested.toNull value wSerially
|
||||
, benchIO "toNull3" $ Nested.toNull3 value wSerially
|
||||
, benchIO "filterAllOut" $ Nested.filterAllOut value wSerially
|
||||
, benchIO "filterAllIn" $ Nested.filterAllIn value wSerially
|
||||
, benchIO "filterSome" $ Nested.filterSome value wSerially
|
||||
, benchIO "breakAfterSome" $ Nested.breakAfterSome value wSerially
|
||||
]
|
||||
]
|
||||
, bgroup "zipSerially"
|
||||
[ bgroup "transformation"
|
||||
[ benchIOSink value "fmap" $ Ops.fmap' zipSerially 1
|
||||
]
|
||||
-- XXX needs fixing
|
||||
{-
|
||||
, bgroup "outer-product"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value zipSerially
|
||||
]
|
||||
-}
|
||||
]
|
||||
]
|
||||
zipSerial value = concat [o_1_space_zipSerial_transformation value]
|
||||
|
792
benchmark/lib/Streamly/Benchmark/Groups.hs
Normal file
792
benchmark/lib/Streamly/Benchmark/Groups.hs
Normal file
@ -0,0 +1,792 @@
|
||||
-- |
|
||||
-- Module : Main
|
||||
-- Copyright : (c) 2018 Harendra Kumar
|
||||
--
|
||||
-- License : BSD3
|
||||
-- Maintainer : streamly@composewell.com
|
||||
|
||||
module Streamly.Benchmark.Groups where
|
||||
|
||||
import Control.DeepSeq (NFData(..))
|
||||
import Data.Functor.Identity (Identity, runIdentity)
|
||||
import Data.Monoid (Last(..))
|
||||
import System.Random (randomRIO)
|
||||
|
||||
import qualified GHC.Exts as GHC
|
||||
import qualified Streamly.Benchmark.Prelude as Ops
|
||||
|
||||
import Streamly
|
||||
import qualified Streamly.Data.Fold as FL
|
||||
import qualified Streamly.Prelude as S
|
||||
import qualified Streamly.Internal.Data.Sink as Sink
|
||||
|
||||
import Streamly.Internal.Data.Time.Units
|
||||
import qualified Streamly.Internal.Memory.Array as IA
|
||||
import qualified Streamly.Internal.Data.Fold as IFL
|
||||
import qualified Streamly.Internal.Prelude as IP
|
||||
import qualified Streamly.Internal.Data.Pipe as Pipe
|
||||
|
||||
import qualified NestedOps as Nested
|
||||
import qualified NestedUnfoldOps as NestedUnfold
|
||||
|
||||
import Gauge
|
||||
import Streamly.Benchmark.Common
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- 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)
|
||||
=> Int -> String -> (t IO Int -> IO b) -> Benchmark
|
||||
benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source value
|
||||
|
||||
{-# INLINE benchHoistSink #-}
|
||||
benchHoistSink
|
||||
:: (IsStream t, NFData b)
|
||||
=> Int -> String -> (t Identity Int -> IO b) -> Benchmark
|
||||
benchHoistSink value name f =
|
||||
bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.sourceUnfoldr value
|
||||
|
||||
-- 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)
|
||||
=> Int -> String -> (t Identity Int -> Identity b) -> Benchmark
|
||||
benchIdentitySink value name f = bench name $ nf (f . Ops.sourceUnfoldr value) 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 benchPureSink #-}
|
||||
benchPureSink :: NFData b => Int -> String -> (SerialT Identity Int -> b) -> Benchmark
|
||||
benchPureSink value name f = benchPure name (Ops.sourceUnfoldr value) f
|
||||
|
||||
benchIO :: (NFData b) => String -> (Int -> IO b) -> Benchmark
|
||||
benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Serial : O(1) Space
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
o_1_space_serial_pure :: Int -> [Benchmark]
|
||||
o_1_space_serial_pure value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"pure"
|
||||
[ benchPureSink value "id" id
|
||||
, benchPureSink1 "eqBy" (Ops.eqByPure value)
|
||||
, benchPureSink value "==" Ops.eqInstance
|
||||
, benchPureSink value "/=" Ops.eqInstanceNotEq
|
||||
, benchPureSink1 "cmpBy" (Ops.cmpByPure value)
|
||||
, benchPureSink value "<" Ops.ordInstance
|
||||
, benchPureSink value "min" Ops.ordInstanceMin
|
||||
, benchPureSrc "IsList.fromList" (Ops.sourceIsList value)
|
||||
-- length is used to check for foldr/build fusion
|
||||
, benchPureSink
|
||||
value
|
||||
"length . IsList.toList"
|
||||
(length . GHC.toList)
|
||||
, benchPureSrc "IsString.fromString" (Ops.sourceIsString value)
|
||||
, benchPureSink value "showsPrec pure streams" Ops.showInstance
|
||||
, benchPureSink value "foldl'" Ops.pureFoldl'
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_foldable :: Int -> [Benchmark]
|
||||
o_1_space_serial_foldable value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"foldable"
|
||||
-- Foldable instance
|
||||
-- type class operations
|
||||
[ bench "foldl'" $ nf (Ops.foldableFoldl' value) 1
|
||||
, bench "foldrElem" $ nf (Ops.foldableFoldrElem value) 1
|
||||
-- , bench "null" $ nf (Ops.foldableNull value) 1
|
||||
, bench "elem" $ nf (Ops.foldableElem value) 1
|
||||
, bench "length" $ nf (Ops.foldableLength value) 1
|
||||
, bench "sum" $ nf (Ops.foldableSum value) 1
|
||||
, bench "product" $ nf (Ops.foldableProduct value) 1
|
||||
, bench "minimum" $ nf (Ops.foldableMin value) 1
|
||||
, bench "maximum" $ nf (Ops.foldableMax value) 1
|
||||
, bench "length . toList" $
|
||||
nf (length . Ops.foldableToList value) 1
|
||||
-- folds
|
||||
, bench "notElem" $ nf (Ops.foldableNotElem value) 1
|
||||
, bench "find" $ nf (Ops.foldableFind value) 1
|
||||
, bench "all" $ nf (Ops.foldableAll value) 1
|
||||
, bench "any" $ nf (Ops.foldableAny value) 1
|
||||
, bench "and" $ nf (Ops.foldableAnd value) 1
|
||||
, bench "or" $ nf (Ops.foldableOr value) 1
|
||||
-- Note: minimumBy/maximumBy do not work in constant memory they are in
|
||||
-- the O(n) group of benchmarks down below in this file.
|
||||
-- Applicative and Traversable operations
|
||||
-- TBD: traverse_
|
||||
, benchIOSink1 "mapM_" (Ops.foldableMapM_ value)
|
||||
-- TBD: for_
|
||||
-- TBD: forM_
|
||||
, benchIOSink1 "sequence_" (Ops.foldableSequence_ value)
|
||||
-- TBD: sequenceA_
|
||||
-- TBD: asum
|
||||
-- , benchIOSink1 "msum" (Ops.foldableMsum value)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_generation :: Int -> [Benchmark]
|
||||
o_1_space_serial_generation value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"generation"
|
||||
-- Most basic, barely stream continuations running
|
||||
[ benchIOSrc serially "unfoldr" (Ops.sourceUnfoldr value)
|
||||
, benchIOSrc serially "unfoldrM" (Ops.sourceUnfoldrM value)
|
||||
, benchIOSrc serially "intFromTo" (Ops.sourceIntFromTo value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"intFromThenTo"
|
||||
(Ops.sourceIntFromThenTo value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"integerFromStep"
|
||||
(Ops.sourceIntegerFromStep value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"fracFromThenTo"
|
||||
(Ops.sourceFracFromThenTo value)
|
||||
, benchIOSrc serially "fracFromTo" (Ops.sourceFracFromTo value)
|
||||
, benchIOSrc serially "fromList" (Ops.sourceFromList value)
|
||||
, benchIOSrc serially "fromListM" (Ops.sourceFromListM value)
|
||||
-- These are essentially cons and consM
|
||||
, benchIOSrc
|
||||
serially
|
||||
"fromFoldable"
|
||||
(Ops.sourceFromFoldable value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"fromFoldableM"
|
||||
(Ops.sourceFromFoldableM value)
|
||||
, benchIOSrc serially "currentTime/0.00001s" $
|
||||
Ops.currentTime value 0.00001
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_elimination :: Int -> [Benchmark]
|
||||
o_1_space_serial_elimination value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"elimination"
|
||||
[ bgroup
|
||||
"reduce"
|
||||
[ bgroup
|
||||
"IO"
|
||||
[ benchIOSink value "foldl'" Ops.foldl'Reduce
|
||||
, benchIOSink value "foldl1'" Ops.foldl1'Reduce
|
||||
, benchIOSink value "foldlM'" Ops.foldlM'Reduce
|
||||
]
|
||||
, bgroup
|
||||
"Identity"
|
||||
[ benchIdentitySink value "foldl'" Ops.foldl'Reduce
|
||||
, benchIdentitySink
|
||||
value
|
||||
"foldl1'"
|
||||
Ops.foldl1'Reduce
|
||||
, benchIdentitySink
|
||||
value
|
||||
"foldlM'"
|
||||
Ops.foldlM'Reduce
|
||||
]
|
||||
]
|
||||
, bgroup
|
||||
"build"
|
||||
[ bgroup
|
||||
"IO"
|
||||
[ benchIOSink
|
||||
value
|
||||
"foldrMElem"
|
||||
(Ops.foldrMElem value)
|
||||
]
|
||||
, bgroup
|
||||
"Identity"
|
||||
[ benchIdentitySink
|
||||
value
|
||||
"foldrMElem"
|
||||
(Ops.foldrMElem value)
|
||||
, benchIdentitySink
|
||||
value
|
||||
"foldrMToStreamLength"
|
||||
(S.length . runIdentity . Ops.foldrMToStream)
|
||||
, benchPureSink
|
||||
value
|
||||
"foldrMToListLength"
|
||||
(length . runIdentity . Ops.foldrMBuild)
|
||||
]
|
||||
]
|
||||
, benchIOSink value "uncons" Ops.uncons
|
||||
, benchIOSink value "toNull" $ Ops.toNull serially
|
||||
, benchIOSink value "mapM_" Ops.mapM_
|
||||
, benchIOSink value "init" Ops.init
|
||||
-- this is too low and causes all benchmarks reported in ns
|
||||
-- , benchIOSink value "head" Ops.head
|
||||
, benchIOSink value "last" Ops.last
|
||||
-- , benchIOSink value "lookup" Ops.lookup
|
||||
, benchIOSink value "find" (Ops.find value)
|
||||
, benchIOSink value "findIndex" (Ops.findIndex value)
|
||||
, benchIOSink value "elemIndex" (Ops.elemIndex value)
|
||||
-- this is too low and causes all benchmarks reported in ns
|
||||
-- , benchIOSink value "null" Ops.null
|
||||
, benchIOSink value "elem" (Ops.elem value)
|
||||
, benchIOSink value "notElem" (Ops.notElem value)
|
||||
, benchIOSink value "all" (Ops.all value)
|
||||
, benchIOSink value "any" (Ops.any value)
|
||||
, benchIOSink value "and" (Ops.and value)
|
||||
, benchIOSink value "or" (Ops.or value)
|
||||
, benchIOSink value "length" Ops.length
|
||||
, benchHoistSink
|
||||
value
|
||||
"length . generally"
|
||||
(Ops.length . IP.generally)
|
||||
, benchIOSink value "sum" Ops.sum
|
||||
, benchIOSink value "product" Ops.product
|
||||
, benchIOSink value "maximumBy" Ops.maximumBy
|
||||
, benchIOSink value "maximum" Ops.maximum
|
||||
, benchIOSink value "minimumBy" Ops.minimumBy
|
||||
, benchIOSink value "minimum" Ops.minimum
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_folds :: Int -> [Benchmark]
|
||||
o_1_space_serial_folds value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"folds"
|
||||
[ benchIOSink value "drain" (S.fold FL.drain)
|
||||
, benchIOSink value "drainN" (S.fold (IFL.drainN value))
|
||||
, benchIOSink
|
||||
value
|
||||
"drainWhileTrue"
|
||||
(S.fold (IFL.drainWhile $ (<=) (value + 1)))
|
||||
, benchIOSink
|
||||
value
|
||||
"drainWhileFalse"
|
||||
(S.fold (IFL.drainWhile $ (>=) (value + 1)))
|
||||
, benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
|
||||
, benchIOSink value "last" (S.fold FL.last)
|
||||
, benchIOSink value "lastN.1" (S.fold (IA.lastN 1))
|
||||
, benchIOSink value "lastN.10" (S.fold (IA.lastN 10))
|
||||
, benchIOSink value "length" (S.fold FL.length)
|
||||
, benchIOSink value "sum" (S.fold FL.sum)
|
||||
, benchIOSink value "product" (S.fold FL.product)
|
||||
, benchIOSink value "maximumBy" (S.fold (FL.maximumBy compare))
|
||||
, benchIOSink value "maximum" (S.fold FL.maximum)
|
||||
, benchIOSink value "minimumBy" (S.fold (FL.minimumBy compare))
|
||||
, benchIOSink value "minimum" (S.fold FL.minimum)
|
||||
, benchIOSink
|
||||
value
|
||||
"mean"
|
||||
(\s ->
|
||||
S.fold
|
||||
FL.mean
|
||||
(S.map (fromIntegral :: Int -> Double) s))
|
||||
, benchIOSink
|
||||
value
|
||||
"variance"
|
||||
(\s ->
|
||||
S.fold
|
||||
FL.variance
|
||||
(S.map (fromIntegral :: Int -> Double) s))
|
||||
, benchIOSink
|
||||
value
|
||||
"stdDev"
|
||||
(\s ->
|
||||
S.fold
|
||||
FL.stdDev
|
||||
(S.map (fromIntegral :: Int -> Double) s))
|
||||
, benchIOSink
|
||||
value
|
||||
"mconcat"
|
||||
(S.fold FL.mconcat . (S.map (Last . Just)))
|
||||
, benchIOSink
|
||||
value
|
||||
"foldMap"
|
||||
(S.fold (FL.foldMap (Last . Just)))
|
||||
, benchIOSink value "index" (S.fold (FL.index (value + 1)))
|
||||
, benchIOSink value "head" (S.fold FL.head)
|
||||
, benchIOSink value "find" (S.fold (FL.find (== (value + 1))))
|
||||
, benchIOSink
|
||||
value
|
||||
"findIndex"
|
||||
(S.fold (FL.findIndex (== (value + 1))))
|
||||
, benchIOSink
|
||||
value
|
||||
"elemIndex"
|
||||
(S.fold (FL.elemIndex (value + 1)))
|
||||
, benchIOSink value "null" (S.fold FL.null)
|
||||
, benchIOSink value "elem" (S.fold (FL.elem (value + 1)))
|
||||
, benchIOSink value "notElem" (S.fold (FL.notElem (value + 1)))
|
||||
, benchIOSink value "all" (S.fold (FL.all (<= (value + 1))))
|
||||
, benchIOSink value "any" (S.fold (FL.any (> (value + 1))))
|
||||
, benchIOSink
|
||||
value
|
||||
"and"
|
||||
(\s -> S.fold FL.and (S.map (<= (value + 1)) s))
|
||||
, benchIOSink
|
||||
value
|
||||
"or"
|
||||
(\s -> S.fold FL.or (S.map (> (value + 1)) s))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_foldMultiStream :: Int -> [Benchmark]
|
||||
o_1_space_serial_foldMultiStream value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"fold-multi-stream"
|
||||
[ benchIOSink1 "eqBy" (Ops.eqBy value)
|
||||
, benchIOSink1 "cmpBy" (Ops.cmpBy value)
|
||||
, benchIOSink value "isPrefixOf" Ops.isPrefixOf
|
||||
, benchIOSink value "isSubsequenceOf" Ops.isSubsequenceOf
|
||||
, benchIOSink value "stripPrefix" Ops.stripPrefix
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_foldsTransforms :: Int -> [Benchmark]
|
||||
o_1_space_serial_foldsTransforms value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"folds-transforms"
|
||||
[ benchIOSink value "drain" (S.fold FL.drain)
|
||||
, benchIOSink value "lmap" (S.fold (IFL.lmap (+ 1) FL.drain))
|
||||
, benchIOSink
|
||||
value
|
||||
"pipe-mapM"
|
||||
(S.fold
|
||||
(IFL.transform
|
||||
(Pipe.mapM (\x -> return $ x + 1))
|
||||
FL.drain))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_foldsCompositions :: Int -> [Benchmark]
|
||||
o_1_space_serial_foldsCompositions value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"folds-compositions" -- Applicative
|
||||
[ benchIOSink
|
||||
value
|
||||
"all,any"
|
||||
(S.fold
|
||||
((,) <$> FL.all (<= (value + 1)) <*>
|
||||
FL.any (> (value + 1))))
|
||||
, benchIOSink
|
||||
value
|
||||
"sum,length"
|
||||
(S.fold ((,) <$> FL.sum <*> FL.length))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_pipes :: Int -> [Benchmark]
|
||||
o_1_space_serial_pipes value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"pipes"
|
||||
[ benchIOSink value "mapM" (Ops.transformMapM serially 1)
|
||||
, benchIOSink
|
||||
value
|
||||
"compose"
|
||||
(Ops.transformComposeMapM serially 1)
|
||||
, benchIOSink value "tee" (Ops.transformTeeMapM serially 1)
|
||||
, benchIOSink value "zip" (Ops.transformZipMapM serially 1)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_pipesX4 :: Int -> [Benchmark]
|
||||
o_1_space_serial_pipesX4 value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"pipesX4"
|
||||
[ benchIOSink value "mapM" (Ops.transformMapM serially 4)
|
||||
, benchIOSink
|
||||
value
|
||||
"compose"
|
||||
(Ops.transformComposeMapM serially 4)
|
||||
, benchIOSink value "tee" (Ops.transformTeeMapM serially 4)
|
||||
, benchIOSink value "zip" (Ops.transformZipMapM serially 4)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_transformer :: Int -> [Benchmark]
|
||||
o_1_space_serial_transformer value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"transformer"
|
||||
[ benchIOSrc serially "evalState" (Ops.evalStateT value)
|
||||
, benchIOSrc serially "withState" (Ops.withState value)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_transformation :: Int -> [Benchmark]
|
||||
o_1_space_serial_transformation value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"transformation"
|
||||
[ benchIOSink value "scanl" (Ops.scan 1)
|
||||
, benchIOSink value "scanl1'" (Ops.scanl1' 1)
|
||||
, benchIOSink value "map" (Ops.map 1)
|
||||
, benchIOSink value "fmap" (Ops.fmap 1)
|
||||
, benchIOSink value "mapM" (Ops.mapM serially 1)
|
||||
, benchIOSink value "mapMaybe" (Ops.mapMaybe 1)
|
||||
, benchIOSink value "mapMaybeM" (Ops.mapMaybeM 1)
|
||||
, bench "sequence" $
|
||||
nfIO $
|
||||
randomRIO (1, 1000) >>= \n ->
|
||||
Ops.sequence serially (Ops.sourceUnfoldrMAction value n)
|
||||
, benchIOSink value "findIndices" (Ops.findIndices value 1)
|
||||
, benchIOSink value "elemIndices" (Ops.elemIndices value 1)
|
||||
, benchIOSink value "foldrS" (Ops.foldrS 1)
|
||||
, benchIOSink value "foldrSMap" (Ops.foldrSMap 1)
|
||||
, benchIOSink value "foldrT" (Ops.foldrT 1)
|
||||
, benchIOSink value "foldrTMap" (Ops.foldrTMap 1)
|
||||
, benchIOSink value "tap" (Ops.tap 1)
|
||||
, benchIOSink value "tapRate 1 second" (Ops.tapRate 1)
|
||||
, benchIOSink value "pollCounts 1 second" (Ops.pollCounts 1)
|
||||
, benchIOSink value "tapAsync" (Ops.tapAsync 1)
|
||||
, benchIOSink value "tapAsyncS" (Ops.tapAsyncS 1)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_transformationX4 :: Int -> [Benchmark]
|
||||
o_1_space_serial_transformationX4 value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"transformationX4"
|
||||
[ benchIOSink value "scan" (Ops.scan 4)
|
||||
, benchIOSink value "scanl1'" (Ops.scanl1' 4)
|
||||
, benchIOSink value "map" (Ops.map 4)
|
||||
, benchIOSink value "fmap" (Ops.fmap 4)
|
||||
, benchIOSink value "mapM" (Ops.mapM serially 4)
|
||||
, benchIOSink value "mapMaybe" (Ops.mapMaybe 4)
|
||||
, benchIOSink value "mapMaybeM" (Ops.mapMaybeM 4)
|
||||
-- , bench "sequence" $ nfIO $ randomRIO (1,1000) >>= \n ->
|
||||
-- Ops.sequence serially (Ops.sourceUnfoldrMAction n)
|
||||
, benchIOSink value "findIndices" (Ops.findIndices value 4)
|
||||
, benchIOSink value "elemIndices" (Ops.elemIndices value 4)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_filtering :: Int -> [Benchmark]
|
||||
o_1_space_serial_filtering value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"filtering"
|
||||
[ benchIOSink value "filter-even" (Ops.filterEven 1)
|
||||
, benchIOSink value "filter-all-out" (Ops.filterAllOut value 1)
|
||||
, benchIOSink value "filter-all-in" (Ops.filterAllIn value 1)
|
||||
, benchIOSink value "take-all" (Ops.takeAll value 1)
|
||||
, benchIOSink
|
||||
value
|
||||
"takeByTime-all"
|
||||
(Ops.takeByTime (NanoSecond64 maxBound) 1)
|
||||
, benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 1)
|
||||
--, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 1)
|
||||
-- "drop-one" is dual to "last"
|
||||
, benchIOSink value "drop-one" (Ops.dropOne 1)
|
||||
, benchIOSink value "drop-all" (Ops.dropAll value 1)
|
||||
, benchIOSink
|
||||
value
|
||||
"dropByTime-all"
|
||||
(Ops.dropByTime (NanoSecond64 maxBound) 1)
|
||||
, benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 1)
|
||||
--, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 1)
|
||||
, benchIOSink
|
||||
value
|
||||
"dropWhile-false"
|
||||
(Ops.dropWhileFalse value 1)
|
||||
, benchIOSink value "deleteBy" (Ops.deleteBy value 1)
|
||||
, benchIOSink value "intersperse" (Ops.intersperse value 1)
|
||||
, benchIOSink value "insertBy" (Ops.insertBy value 1)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_filteringX4 :: Int -> [Benchmark]
|
||||
o_1_space_serial_filteringX4 value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"filteringX4"
|
||||
[ benchIOSink value "filter-even" (Ops.filterEven 4)
|
||||
, benchIOSink value "filter-all-out" (Ops.filterAllOut value 4)
|
||||
, benchIOSink value "filter-all-in" (Ops.filterAllIn value 4)
|
||||
, benchIOSink value "take-all" (Ops.takeAll value 4)
|
||||
, benchIOSink value "takeWhile-true" (Ops.takeWhileTrue value 4)
|
||||
--, benchIOSink value "takeWhileM-true" (Ops.takeWhileMTrue 4)
|
||||
, benchIOSink value "drop-one" (Ops.dropOne 4)
|
||||
, benchIOSink value "drop-all" (Ops.dropAll value 4)
|
||||
, benchIOSink value "dropWhile-true" (Ops.dropWhileTrue value 4)
|
||||
--, benchIOSink value "dropWhileM-true" (Ops.dropWhileMTrue 4)
|
||||
, benchIOSink
|
||||
value
|
||||
"dropWhile-false"
|
||||
(Ops.dropWhileFalse value 4)
|
||||
, benchIOSink value "deleteBy" (Ops.deleteBy value 4)
|
||||
, benchIOSink value "intersperse" (Ops.intersperse value 4)
|
||||
, benchIOSink value "insertBy" (Ops.insertBy value 4)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_joining :: Int -> [Benchmark]
|
||||
o_1_space_serial_joining value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"joining"
|
||||
[ benchIOSrc1 "zip (2,x/2)" (Ops.zip (value `div` 2))
|
||||
, benchIOSrc1 "zipM (2,x/2)" (Ops.zipM (value `div` 2))
|
||||
, benchIOSrc1 "mergeBy (2,x/2)" (Ops.mergeBy (value `div` 2))
|
||||
, benchIOSrc1 "serial (2,x/2)" (Ops.serial2 (value `div` 2))
|
||||
, benchIOSrc1 "append (2,x/2)" (Ops.append2 (value `div` 2))
|
||||
, benchIOSrc1 "serial (2,2,x/4)" (Ops.serial4 (value `div` 4))
|
||||
, benchIOSrc1 "append (2,2,x/4)" (Ops.append4 (value `div` 4))
|
||||
, benchIOSrc1 "wSerial (2,x/2)" (Ops.wSerial2 value) -- XXX Move this elsewhere?
|
||||
, benchIOSrc1 "interleave (2,x/2)" (Ops.interleave2 value)
|
||||
, benchIOSrc1 "roundRobin (2,x/2)" (Ops.roundRobin2 value)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_concatFoldable :: Int -> [Benchmark]
|
||||
o_1_space_serial_concatFoldable value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"concat-foldable"
|
||||
[ benchIOSrc
|
||||
serially
|
||||
"foldMapWith"
|
||||
(Ops.sourceFoldMapWith value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"foldMapWithM"
|
||||
(Ops.sourceFoldMapWithM value)
|
||||
, benchIOSrc serially "foldMapM" (Ops.sourceFoldMapM value)
|
||||
, benchIOSrc
|
||||
serially
|
||||
"foldWithConcatMapId"
|
||||
(Ops.sourceConcatMapId value)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_concatSerial :: Int -> [Benchmark]
|
||||
o_1_space_serial_concatSerial value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"concat-serial"
|
||||
[ benchIOSrc1
|
||||
"concatMapPure (2,x/2)"
|
||||
(Ops.concatMapPure 2 (value `div` 2))
|
||||
, benchIOSrc1
|
||||
"concatMap (2,x/2)"
|
||||
(Ops.concatMap 2 (value `div` 2))
|
||||
, benchIOSrc1
|
||||
"concatMap (x/2,2)"
|
||||
(Ops.concatMap (value `div` 2) 2)
|
||||
, benchIOSrc1
|
||||
"concatMapRepl (x/4,4)"
|
||||
(Ops.concatMapRepl4xN value)
|
||||
, benchIOSrc1
|
||||
"concatUnfoldRepl (x/4,4)"
|
||||
(Ops.concatUnfoldRepl4xN value)
|
||||
, benchIOSrc1
|
||||
"concatMapWithSerial (2,x/2)"
|
||||
(Ops.concatMapWithSerial 2 (value `div` 2))
|
||||
, benchIOSrc1
|
||||
"concatMapWithSerial (x/2,2)"
|
||||
(Ops.concatMapWithSerial (value `div` 2) 2)
|
||||
, benchIOSrc1
|
||||
"concatMapWithAppend (2,x/2)"
|
||||
(Ops.concatMapWithAppend 2 (value `div` 2))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_outerProductStreams :: Int -> [Benchmark]
|
||||
o_1_space_serial_outerProductStreams value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"outer-product-streams"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value serially
|
||||
, benchIO "toNull" $ Nested.toNull value serially
|
||||
, benchIO "toNull3" $ Nested.toNull3 value serially
|
||||
, benchIO "filterAllOut" $ Nested.filterAllOut value serially
|
||||
, benchIO "filterAllIn" $ Nested.filterAllIn value serially
|
||||
, benchIO "filterSome" $ Nested.filterSome value serially
|
||||
, benchIO "breakAfterSome" $
|
||||
Nested.breakAfterSome value serially
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_outerProductUnfolds :: Int -> [Benchmark]
|
||||
o_1_space_serial_outerProductUnfolds value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"outer-product-unfolds"
|
||||
[ benchIO "toNull" $ NestedUnfold.toNull value
|
||||
, benchIO "toNull3" $ NestedUnfold.toNull3 value
|
||||
, benchIO "concat" $ NestedUnfold.concat value
|
||||
, benchIO "filterAllOut" $ NestedUnfold.filterAllOut value
|
||||
, benchIO "filterAllIn" $ NestedUnfold.filterAllIn value
|
||||
, benchIO "filterSome" $ NestedUnfold.filterSome value
|
||||
, benchIO "breakAfterSome" $ NestedUnfold.breakAfterSome value
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
o_1_space_serial_mixed :: Int -> [Benchmark]
|
||||
o_1_space_serial_mixed value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
-- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
|
||||
-- library. If scan/fold followed by a map is efficient enough we may not
|
||||
-- need monolithic implementations of these.
|
||||
[ bgroup
|
||||
"mixed"
|
||||
[ benchIOSink value "scanl-map" (Ops.scanMap 1)
|
||||
, benchIOSink value "foldl-map" Ops.foldl'ReduceMap
|
||||
, benchIOSink value "sum-product-fold" Ops.sumProductFold
|
||||
, benchIOSink value "sum-product-scan" Ops.sumProductScan
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_serial_mixedX4 :: Int -> [Benchmark]
|
||||
o_1_space_serial_mixedX4 value =
|
||||
[ bgroup
|
||||
"serially"
|
||||
[ bgroup
|
||||
"mixedX4"
|
||||
[ benchIOSink value "scan-map" (Ops.scanMap 4)
|
||||
, benchIOSink value "drop-map" (Ops.dropMap 4)
|
||||
, benchIOSink value "drop-scan" (Ops.dropScan 4)
|
||||
, benchIOSink value "take-drop" (Ops.takeDrop value 4)
|
||||
, benchIOSink value "take-scan" (Ops.takeScan value 4)
|
||||
, benchIOSink value "take-map" (Ops.takeMap value 4)
|
||||
, benchIOSink value "filter-drop" (Ops.filterDrop value 4)
|
||||
, benchIOSink value "filter-take" (Ops.filterTake value 4)
|
||||
, benchIOSink value "filter-scan" (Ops.filterScan 4)
|
||||
, benchIOSink value "filter-scanl1" (Ops.filterScanl1 4)
|
||||
, benchIOSink value "filter-map" (Ops.filterMap value 4)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_wSerial_transformation :: Int -> [Benchmark]
|
||||
o_1_space_wSerial_transformation value =
|
||||
[ bgroup
|
||||
"wSerially"
|
||||
[ bgroup
|
||||
"transformation"
|
||||
[benchIOSink value "fmap" $ Ops.fmap' wSerially 1]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_wSerial_concatMap :: Int -> [Benchmark]
|
||||
o_1_space_wSerial_concatMap value =
|
||||
[ bgroup
|
||||
"wSerially"
|
||||
[ bgroup
|
||||
"concatMap"
|
||||
[ benchIOSrc1
|
||||
"concatMapWithWSerial (2,x/2)"
|
||||
(Ops.concatMapWithWSerial 2 (value `div` 2))
|
||||
, benchIOSrc1
|
||||
"concatMapWithWSerial (x/2,2)"
|
||||
(Ops.concatMapWithWSerial (value `div` 2) 2)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_wSerial_outerProduct :: Int -> [Benchmark]
|
||||
o_1_space_wSerial_outerProduct value =
|
||||
[ bgroup
|
||||
"wSerially"
|
||||
[ bgroup
|
||||
"outer-product"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value wSerially
|
||||
, benchIO "toNull" $ Nested.toNull value wSerially
|
||||
, benchIO "toNull3" $ Nested.toNull3 value wSerially
|
||||
, benchIO "filterAllOut" $ Nested.filterAllOut value wSerially
|
||||
, benchIO "filterAllIn" $ Nested.filterAllIn value wSerially
|
||||
, benchIO "filterSome" $ Nested.filterSome value wSerially
|
||||
, benchIO "breakAfterSome" $
|
||||
Nested.breakAfterSome value wSerially
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
o_1_space_zipSerial_transformation :: Int -> [Benchmark]
|
||||
o_1_space_zipSerial_transformation value =
|
||||
[ bgroup
|
||||
"zipSerially"
|
||||
[ bgroup
|
||||
"transformation"
|
||||
[benchIOSink value "fmap" $ Ops.fmap' zipSerially 1]
|
||||
-- XXX needs fixing
|
||||
{-
|
||||
, bgroup "outer-product"
|
||||
[ benchIO "toNullAp" $ Nested.toNullAp value zipSerially
|
||||
]
|
||||
-}
|
||||
]
|
||||
]
|
@ -134,9 +134,13 @@ library
|
||||
|
||||
library lib-prelude
|
||||
import: lib-options, bench-depends
|
||||
hs-source-dirs: lib
|
||||
hs-source-dirs: lib, .
|
||||
exposed-modules:
|
||||
Streamly.Benchmark.Prelude
|
||||
, Streamly.Benchmark.Groups
|
||||
other-modules: Streamly.Benchmark.Common
|
||||
, NestedOps
|
||||
, NestedUnfoldOps
|
||||
-- XXX GHCJS build fails for this library.
|
||||
if impl(ghcjs)
|
||||
buildable: False
|
||||
|
Loading…
Reference in New Issue
Block a user