on master help sign in
Move benchmarks of SmallArray out of common array benchmark mess
fd55f07adithyaov
benchmark/Streamly/Benchmark/Data/Array.hs+1−8
@@ -173,9 +173,7 @@ o_1_space_transformationX4 value =
173 ]
173 ]
174
174
175moduleName :: String
175moduleName :: String
176−#ifdef DATA_SMALLARRAY
177−moduleName = "Data.SmallArray"
178−#elif defined(MEMORY_ARRAY)
176+#if defined(MEMORY_ARRAY)
179moduleName = "Data.Array.Foreign"
177moduleName = "Data.Array.Foreign"
180#elif defined(DATA_ARRAY_PRIM)
178#elif defined(DATA_ARRAY_PRIM)
181moduleName = "Data.Array.Prim"
179moduleName = "Data.Array.Prim"
@@ -185,13 +183,8 @@ moduleName = "Data.Array.Prim.Pinned"
185moduleName = "Data.Array"
183moduleName = "Data.Array"
186#endif
184#endif
187
185
188−#ifdef DATA_SMALLARRAY
189−defStreamSize :: Int
190−defStreamSize = 128
191−#else
192defStreamSize :: Int
186defStreamSize :: Int
193defStreamSize = defaultStreamSize
187defStreamSize = defaultStreamSize
194−#endif
195
188
196main :: IO ()
189main :: IO ()
197main = runWithCLIOpts defStreamSize allBenchmarks
190main = runWithCLIOpts defStreamSize allBenchmarks
benchmark/Streamly/Benchmark/Data/Array/Common.hsnew file+188
@@ -0,0 +1,188 @@
1+
2+
3+-------------------------------------------------------------------------------
4+-- Benchmark helpers
5+-------------------------------------------------------------------------------
6+
7+{-# INLINE benchIO #-}
8+benchIO :: NFData b => String -> (Int -> IO a) -> (a -> b) -> Benchmark
9+benchIO name src f = bench name $ nfIO $
10+ randomRIO (1,1) >>= src >>= return . f
11+
12+{-# INLINE benchPureSink #-}
13+benchPureSink :: NFData b => Int -> String -> (Stream Int -> b) -> Benchmark
14+benchPureSink value name f = benchIO name (sourceIntFromTo value) f
15+
16+{-# INLINE benchIO' #-}
17+benchIO' :: NFData b => String -> (Int -> IO a) -> (a -> IO b) -> Benchmark
18+benchIO' name src f = bench name $ nfIO $
19+ randomRIO (1,1) >>= src >>= f
20+
21+{-# INLINE benchIOSink #-}
22+benchIOSink :: NFData b => Int -> String -> (Stream Int -> IO b) -> Benchmark
23+benchIOSink value name f = benchIO' name (sourceIntFromTo value) f
24+
25+-------------------------------------------------------------------------------
26+-- Bench Ops
27+-------------------------------------------------------------------------------
28+
29+{-# INLINE sourceUnfoldr #-}
30+sourceUnfoldr :: MonadIO m => Int -> Int -> m (Stream Int)
31+sourceUnfoldr value n = S.fold (A.writeN value) $ S.unfoldr step n
32+ where
33+ step cnt =
34+ if cnt > n + value
35+ then Nothing
36+ else (Just (cnt, cnt + 1))
37+
38+{-# INLINE sourceIntFromTo #-}
39+sourceIntFromTo :: MonadIO m => Int -> Int -> m (Stream Int)
40+sourceIntFromTo value n = S.fold (A.writeN value) $ S.enumerateFromTo n (n + value)
41+
42+{-# INLINE sourceFromList #-}
43+sourceFromList :: MonadIO m => Int -> Int -> m (Stream Int)
44+sourceFromList value n = S.fold (A.writeN value) $ S.fromList [n..n+value]
45+
46+-------------------------------------------------------------------------------
47+-- Transformation
48+-------------------------------------------------------------------------------
49+
50+{-# INLINE composeN #-}
51+composeN :: P.Monad m
52+ => Int -> (Stream Int -> m (Stream Int)) -> Stream Int -> m (Stream Int)
53+composeN n f x =
54+ case n of
55+ 1 -> f x
56+ 2 -> f x P.>>= f
57+ 3 -> f x P.>>= f P.>>= f
58+ 4 -> f x P.>>= f P.>>= f P.>>= f
59+ _ -> undefined
60+
61+{-# INLINE scanl' #-}
62+{-# INLINE scanl1' #-}
63+{-# INLINE map #-}
64+
65+scanl' , scanl1', map
66+ :: MonadIO m => Int -> Int -> Stream Int -> m (Stream Int)
67+
68+
69+{-# INLINE onArray #-}
70+onArray
71+ :: MonadIO m => Int -> (S.SerialT m Int -> S.SerialT m Int)
72+ -> Stream Int
73+ -> m (Stream Int)
74+onArray value f arr = S.fold (A.writeN value) $ f $ (S.unfold A.read arr)
75+
76+scanl' value n = composeN n $ onArray value $ S.scanl' (+) 0
77+scanl1' value n = composeN n $ onArray value $ S.scanl1' (+)
78+map value n = composeN n $ onArray value $ S.map (+1)
79+-- map n = composeN n $ A.map (+1)
80+
81+{-# INLINE eqInstance #-}
82+eqInstance :: Stream Int -> Bool
83+eqInstance src = src == src
84+
85+{-# INLINE eqInstanceNotEq #-}
86+eqInstanceNotEq :: Stream Int -> Bool
87+eqInstanceNotEq src = src P./= src
88+
89+{-# INLINE ordInstance #-}
90+ordInstance :: Stream Int -> Bool
91+ordInstance src = src P.< src
92+
93+{-# INLINE ordInstanceMin #-}
94+ordInstanceMin :: Stream Int -> Stream Int
95+ordInstanceMin src = P.min src src
96+
97+{-# INLINE showInstance #-}
98+showInstance :: Stream Int -> P.String
99+showInstance src = P.show src
100+
101+{-# INLINE pureFoldl' #-}
102+pureFoldl' :: MonadIO m => Stream Int -> m Int
103+pureFoldl' = S.foldl' (+) 0 . S.unfold A.read
104+
105+
106+-------------------------------------------------------------------------------
107+-- Elimination
108+-------------------------------------------------------------------------------
109+
110+{-# INLINE unfoldReadDrain #-}
111+unfoldReadDrain :: MonadIO m => Stream Int -> m ()
112+unfoldReadDrain = S.drain . S.unfold A.read
113+
114+{-# INLINE toStreamRevDrain #-}
115+toStreamRevDrain :: MonadIO m => Stream Int -> m ()
116+toStreamRevDrain = S.drain . A.toStreamRev
117+
118+-------------------------------------------------------------------------------
119+-- Bench groups
120+-------------------------------------------------------------------------------
121+
122+common_o_1_space_generation :: Int -> [Benchmark]
123+common_o_1_space_generation value =
124+ [ bgroup
125+ "generation"
126+ [ benchIOSrc "writeN . intFromTo" (sourceIntFromTo value)
127+ , benchIOSrc
128+ "fromList . intFromTo"
129+ (sourceIntFromToFromList value)
130+ , benchIOSrc "writeN . unfoldr" (sourceUnfoldr value)
131+ , benchIOSrc "writeN . fromList" (sourceFromList value)
132+ , benchPureSink value "show" showInstance
133+ ]
134+ ]
135+
136+common_o_1_space_elimination :: Int -> [Benchmark]
137+common_o_1_space_elimination value =
138+ [ bgroup "elimination"
139+ [ benchPureSink value "id" id
140+ , benchPureSink value "==" eqInstance
141+ , benchPureSink value "/=" eqInstanceNotEq
142+ , benchPureSink value "<" ordInstance
143+ , benchPureSink value "min" ordInstanceMin
144+ , benchIOSink value "foldl'" pureFoldl'
145+ , benchIOSink value "read" unfoldReadDrain
146+ , benchIOSink value "toStreamRev" toStreamRevDrain
147+ ]
148+ ]
149+
150+common_o_n_heap_serial :: Int -> [Benchmark]
151+common_o_n_heap_serial value =
152+ [ bgroup "elimination"
153+ [
154+ -- Converting the stream to an array
155+ benchFold "writeN" (S.fold (A.writeN value))
156+ (P.sourceUnfoldrM value)
157+ ]
158+ ]
159+
160+common_o_1_space_transformation :: Int -> [Benchmark]
161+common_o_1_space_transformation value =
162+ [ bgroup "transformation"
163+ [ benchIOSink value "scanl'" (scanl' value 1)
164+ , benchIOSink value "scanl1'" (scanl1' value 1)
165+ , benchIOSink value "map" (map value 1)
166+ ]
167+ ]
168+
169+common_o_1_space_transformationX4 :: Int -> [Benchmark]
170+common_o_1_space_transformationX4 value =
171+ [ bgroup "transformationX4"
172+ [ benchIOSink value "scanl'" (scanl' value 4)
173+ , benchIOSink value "scanl1'" (scanl1' value 4)
174+ , benchIOSink value "map" (map value 4)
175+ ]
176+ ]
177+
178+commonBenchmarks :: Int -> [Benchmark]
179+commonBenchmarks size =
180+ [ bgroup (o_1_space_prefix moduleName) $ concat
181+ [ common_o_1_space_generation size
182+ , common_o_1_space_elimination size
183+ , common_o_1_space_transformation size
184+ , common_o_1_space_transformationX4 size
185+ ]
186+ , bgroup (o_n_space_prefix moduleName) $
187+ common_o_n_heap_serial size
188+ ]
benchmark/Streamly/Benchmark/Data/Array/CommonImports.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE FlexibleContexts #-}
2+
3+import Control.DeepSeq (NFData(..))
4+import System.Random (randomRIO)
5+
6+import qualified Streamly.Prelude as S
7+
8+import Gauge
9+import Streamly.Benchmark.Common hiding (benchPureSrc)
10+import qualified Streamly.Benchmark.Prelude as P
11+
12+
13+import Control.Monad.IO.Class (MonadIO)
14+
15+import Prelude as P hiding (map)
benchmark/Streamly/Benchmark/Data/Array/SmallArray.hsnew file+94
@@ -0,0 +1,94 @@
1+{-# LANGUAGE CPP #-}
2+
3+#include "Streamly/Benchmark/Data/Array/CommonImports.hs"
4+
5+import Control.DeepSeq (deepseq)
6+
7+import qualified Streamly.Internal.Data.SmallArray as A
8+type Stream = A.SmallArray
9+
10+#include "Streamly/Benchmark/Data/Array/Common.hs"
11+
12+-------------------------------------------------------------------------------
13+-- Benchmark helpers
14+-------------------------------------------------------------------------------
15+
16+-- Drain a source that generates an array in the IO monad
17+{-# INLINE benchIOSrc #-}
18+benchIOSrc :: NFData a => String -> (Int -> IO (Stream a)) -> Benchmark
19+benchIOSrc name src = benchIO name src id
20+
21+-------------------------------------------------------------------------------
22+-- Bench Ops
23+-------------------------------------------------------------------------------
24+
25+{-# INLINE sourceIntFromToFromList #-}
26+sourceIntFromToFromList :: MonadIO m => Int -> Int -> m (Stream Int)
27+sourceIntFromToFromList value n = P.return $ A.fromListN value $ [n..n + value]
28+
29+{-# INLINE readInstance #-}
30+readInstance :: P.String -> Stream Int
31+readInstance str =
32+ let r = P.reads str
33+ in case r of
34+ [(x,"")] -> x
35+ _ -> P.error "readInstance: no parse"
36+
37+#ifdef DEVBUILD
38+{-
39+{-# INLINE foldableFoldl' #-}
40+foldableFoldl' :: Stream Int -> Int
41+foldableFoldl' = F.foldl' (+) 0
42+
43+{-# INLINE foldableSum #-}
44+foldableSum :: Stream Int -> Int
45+foldableSum = P.sum
46+-}
47+#endif
48+
49+-------------------------------------------------------------------------------
50+-- Bench groups
51+-------------------------------------------------------------------------------
52+
53+o_1_space_generation :: Int -> [Benchmark]
54+o_1_space_generation value =
55+ [ bgroup
56+ "generation"
57+ [ let testStr =
58+ "fromListN " ++
59+ show (value + 1) ++
60+ "[1" ++ concat (replicate value ",1") ++ "]"
61+ in testStr `deepseq` (bench "read" $ nf readInstance testStr)
62+ ]
63+ ]
64+
65+{-
66+o_1_space_elimination :: Int -> [Benchmark]
67+o_1_space_elimination value =
68+ [ bgroup "elimination"
69+ [
70+#ifdef DEVBUILD
71+{-
72+ benchPureSink value "foldable/foldl'" foldableFoldl'
73+ , benchPureSink value "foldable/sum" foldableSum
74+-}
75+#endif
76+ ]
77+ ]
78+-}
79+
80+moduleName :: String
81+moduleName = "Data.SmallArray"
82+
83+defStreamSize :: Int
84+defStreamSize = 128
85+
86+main :: IO ()
87+main = runWithCLIOpts defStreamSize allBenchmarks
88+
89+ where
90+
91+ allBenchmarks size =
92+ [ bgroup (o_1_space_prefix moduleName) $
93+ o_1_space_generation size
94+ ] ++ commonBenchmarks size
benchmark/Streamly/Benchmark/Data/ArrayOps.hs+1−16
@@ -14,7 +14,6 @@
14-- DATA_ARRAY
14-- DATA_ARRAY
15-- DATA_ARRAY_PRIM
15-- DATA_ARRAY_PRIM
16-- DATA_ARRAY_PRIM_PINNED
16-- DATA_ARRAY_PRIM_PINNED
17−-- DATA_SMALLARRAY
18
17
19module Streamly.Benchmark.Data.ArrayOps where
18module Streamly.Benchmark.Data.ArrayOps where
20
19
@@ -32,10 +31,7 @@ import qualified Data.Foldable as F
32#endif
31#endif
33#endif
32#endif
34
33
35−#ifdef DATA_SMALLARRAY
36−import qualified Streamly.Internal.Data.SmallArray as A
37−type Stream = A.SmallArray
38−#elif defined(MEMORY_ARRAY)
34+#if defined(MEMORY_ARRAY)
39import qualified GHC.Exts as GHC
35import qualified GHC.Exts as GHC
40import qualified Streamly.Data.Array.Foreign as A
36import qualified Streamly.Data.Array.Foreign as A
41import qualified Streamly.Internal.Data.Array.Foreign as A
37import qualified Streamly.Internal.Data.Array.Foreign as A
@@ -65,7 +61,6 @@ type Stream = A.Array
65-- DATA_ARRAY
61-- DATA_ARRAY
66-- DATA_ARRAY_PRIM
62-- DATA_ARRAY_PRIM
67-- DATA_ARRAY_PRIM_PINNED
63-- DATA_ARRAY_PRIM_PINNED
68−-- DATA_SMALLARRAY
69-------------------------------------------------------------------------------
64-------------------------------------------------------------------------------
70
65
71{-# INLINE sourceUnfoldr #-}
66{-# INLINE sourceUnfoldr #-}
@@ -85,15 +80,10 @@ sourceIntFromTo value n = S.fold (A.writeN value) $ S.enumerateFromTo n (n + val
85sourceFromList :: MonadIO m => Int -> Int -> m (Stream Int)
80sourceFromList :: MonadIO m => Int -> Int -> m (Stream Int)
86sourceFromList value n = S.fold (A.writeN value) $ S.fromList [n..n+value]
81sourceFromList value n = S.fold (A.writeN value) $ S.fromList [n..n+value]
87
82
88−-- Different defination of sourceIntFromToFromList for DATA_SMALLARRAY
89-- CPP:
83-- CPP:
90{-# INLINE sourceIntFromToFromList #-}
84{-# INLINE sourceIntFromToFromList #-}
91sourceIntFromToFromList :: MonadIO m => Int -> Int -> m (Stream Int)
85sourceIntFromToFromList :: MonadIO m => Int -> Int -> m (Stream Int)
92−#ifndef DATA_SMALLARRAY
93sourceIntFromToFromList value n = P.return $ A.fromList $ [n..n + value]
86sourceIntFromToFromList value n = P.return $ A.fromList $ [n..n + value]
94−#else
95−sourceIntFromToFromList value n = P.return $ A.fromListN value $ [n..n + value]
96−#endif
97
87
98-------------------------------------------------------------------------------
88-------------------------------------------------------------------------------
99-- CPP Common to:
89-- CPP Common to:
@@ -104,11 +94,9 @@ sourceIntFromToFromList value n = P.return $ A.fromListN value $ [n..n + value]
104-------------------------------------------------------------------------------
94-------------------------------------------------------------------------------
105
95
106-- CPP:
96-- CPP:
107−#ifndef DATA_SMALLARRAY
108{-# INLINE sourceIntFromToFromStream #-}
97{-# INLINE sourceIntFromToFromStream #-}
109sourceIntFromToFromStream :: MonadIO m => Int -> Int -> m (Stream Int)
98sourceIntFromToFromStream :: MonadIO m => Int -> Int -> m (Stream Int)
110sourceIntFromToFromStream value n = S.fold A.write $ S.enumerateFromTo n (n + value)
99sourceIntFromToFromStream value n = S.fold A.write $ S.enumerateFromTo n (n + value)
111−#endif
112
100
113-------------------------------------------------------------------------------
101-------------------------------------------------------------------------------
114-- CPP Common to:
102-- CPP Common to:
@@ -136,7 +124,6 @@ sourceIsString value n = GHC.fromString (P.replicate (n + value) 'a')
136-- DATA_ARRAY
124-- DATA_ARRAY
137-- DATA_ARRAY_PRIM
125-- DATA_ARRAY_PRIM
138-- DATA_ARRAY_PRIM_PINNED
126-- DATA_ARRAY_PRIM_PINNED
139−-- DATA_SMALLARRAY
140-------------------------------------------------------------------------------
127-------------------------------------------------------------------------------
141
128
142{-# INLINE composeN #-}
129{-# INLINE composeN #-}
@@ -198,7 +185,6 @@ pureFoldl' = S.foldl' (+) 0 . S.unfold A.read
198-- CPP Common to:
185-- CPP Common to:
199-- MEMORY_ARRAY
186-- MEMORY_ARRAY
200-- DATA_ARRAY
187-- DATA_ARRAY
201−-- DATA_SMALLARRAY
202-------------------------------------------------------------------------------
188-------------------------------------------------------------------------------
203
189
204-- CPP:
190-- CPP:
@@ -234,7 +220,6 @@ foldableSum = P.sum
234-- DATA_ARRAY
220-- DATA_ARRAY
235-- DATA_ARRAY_PRIM
221-- DATA_ARRAY_PRIM
236-- DATA_ARRAY_PRIM_PINNED
222-- DATA_ARRAY_PRIM_PINNED
237−-- DATA_SMALLARRAY
238-------------------------------------------------------------------------------
223-------------------------------------------------------------------------------
239
224
240{-# INLINE unfoldReadDrain #-}
225{-# INLINE unfoldReadDrain #-}
benchmark/streamly-benchmarks.cabal+2−4
@@ -167,6 +167,7 @@ library
167
167
168common bench-options
168common bench-options
169 import: compile-options, optimization-options, bench-depends
169 import: compile-options, optimization-options, bench-depends
170+ include-dirs: .
170 ghc-options: -rtsopts
171 ghc-options: -rtsopts
171 if flag(limit-build-mem)
172 if flag(limit-build-mem)
172 ghc-options: +RTS -M512M -RTS
173 ghc-options: +RTS -M512M -RTS
@@ -473,10 +474,7 @@ benchmark Data.Array.Prim
473benchmark Data.SmallArray
474benchmark Data.SmallArray
474 import: bench-options
475 import: bench-options
475 type: exitcode-stdio-1.0
476 type: exitcode-stdio-1.0
476− hs-source-dirs: .
477− main-is: Streamly/Benchmark/Data/Array.hs
477+ main-is: Streamly/Benchmark/Data/Array/SmallArray.hs
478− other-modules: Streamly.Benchmark.Data.ArrayOps
479− cpp-options: -DDATA_SMALLARRAY
480
478
481benchmark Data.Array.Prim.Pinned
479benchmark Data.Array.Prim.Pinned
482 import: bench-options
480 import: bench-options
streamly.cabal+3
@@ -56,6 +56,9 @@ extra-source-files:
56 benchmark/bench-report/bin/build-lib.sh
56 benchmark/bench-report/bin/build-lib.sh
57 benchmark/bench-report/cabal.project
57 benchmark/bench-report/cabal.project
58 benchmark/Streamly/Benchmark/Data/*.hs
58 benchmark/Streamly/Benchmark/Data/*.hs
59+ benchmark/Streamly/Benchmark/Data/Array/Common.hs
60+ benchmark/Streamly/Benchmark/Data/Array/CommonImports.hs
61+ benchmark/Streamly/Benchmark/Data/Array/SmallArray.hs
59 benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs
62 benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs
60 benchmark/Streamly/Benchmark/Data/Parser/*.hs
63 benchmark/Streamly/Benchmark/Data/Parser/*.hs
61 benchmark/Streamly/Benchmark/Data/Stream/*.hs
64 benchmark/Streamly/Benchmark/Data/Stream/*.hs