on master help sign in
Add more concatMap benchmarks
8552589Harendra Kumar
benchmark/BaseStreams.hs+8−4
@@ -99,8 +99,10 @@ main =
99 , benchIO "mapM" (D.mapM 1) D.sourceUnfoldrM
99 , benchIO "mapM" (D.mapM 1) D.sourceUnfoldrM
100 , benchIO "mapMaybe" (D.mapMaybe 1) D.sourceUnfoldrM
100 , benchIO "mapMaybe" (D.mapMaybe 1) D.sourceUnfoldrM
101 , benchIO "mapMaybeM" (D.mapMaybeM 1) D.sourceUnfoldrM
101 , benchIO "mapMaybeM" (D.mapMaybeM 1) D.sourceUnfoldrM
102− , benchIO "concatMap" (D.concatMap 1) (D.sourceUnfoldrMN D.value2)
102+ , benchIO "concatMapNxN" (D.concatMap 1) (D.sourceUnfoldrMN D.value2)
103+ , benchIO "concatMapRepl4xN" D.concatMapRepl4xN
104+ (D.sourceUnfoldrMN (D.value `div` 4))
103− , benchIO "concatMapPure" (D.concatMap 1) (D.sourceUnfoldrN D.value2)
105+ , benchIO "concatMapPureNxN" (D.concatMap 1) (D.sourceUnfoldrN D.value2)
104 , benchIO "intersperse" (D.intersperse 1) (D.sourceUnfoldrMN D.value2)
106 , benchIO "intersperse" (D.intersperse 1) (D.sourceUnfoldrMN D.value2)
105 , benchIO "interspersePure" (D.intersperse 1) (D.sourceUnfoldrN D.value2)
107 , benchIO "interspersePure" (D.intersperse 1) (D.sourceUnfoldrN D.value2)
106 -- , benchIO "foldrS" (D.foldrS 1) D.sourceUnfoldrM
108 -- , benchIO "foldrS" (D.foldrS 1) D.sourceUnfoldrM
@@ -243,8 +245,10 @@ main =
243 , benchIO "mapM" (K.mapM 1) K.sourceUnfoldrM
245 , benchIO "mapM" (K.mapM 1) K.sourceUnfoldrM
244 , benchIO "mapMSerial" (K.mapMSerial 1) K.sourceUnfoldrM
246 , benchIO "mapMSerial" (K.mapMSerial 1) K.sourceUnfoldrM
245 -- , benchIOSrcK "concatMap" K.concatMap
247 -- , benchIOSrcK "concatMap" K.concatMap
246− , benchIO "concatMap" (K.concatMap 1) (K.sourceUnfoldrMN K.value2)
248+ , benchIO "concatMapNxN" (K.concatMap 1) (K.sourceUnfoldrMN K.value2)
247− , benchIO "concatMapPure" (K.concatMap 1) (K.sourceUnfoldrN K.value2)
249+ , benchIO "concatMapPureNxN" (K.concatMap 1) (K.sourceUnfoldrN K.value2)
250+ , benchIO "concatMapRepl4xN" K.concatMapRepl4xN
251+ (K.sourceUnfoldrMN (K.value `div` 4))
248 , benchIO "intersperse" (K.intersperse 1) (K.sourceUnfoldrMN K.value2)
252 , benchIO "intersperse" (K.intersperse 1) (K.sourceUnfoldrMN K.value2)
249 , benchIO "interspersePure" (K.intersperse 1) (K.sourceUnfoldrN K.value2)
253 , benchIO "interspersePure" (K.intersperse 1) (K.sourceUnfoldrN K.value2)
250 , benchIO "foldlS" (K.foldlS 1) K.sourceUnfoldrM
254 , benchIO "foldlS" (K.foldlS 1) K.sourceUnfoldrM
benchmark/Linear.hs+4−1
@@ -336,7 +336,10 @@ main =
336 , benchIOSink "isPrefixOf" Ops.isPrefixOf
336 , benchIOSink "isPrefixOf" Ops.isPrefixOf
337 , benchIOSink "isSubsequenceOf" Ops.isSubsequenceOf
337 , benchIOSink "isSubsequenceOf" Ops.isSubsequenceOf
338 , benchIOSink "stripPrefix" Ops.stripPrefix
338 , benchIOSink "stripPrefix" Ops.stripPrefix
339− , benchIOSrc serially "concatMap" Ops.concatMap
339+ , benchIOSrc serially "concatMap1xN" Ops.concatMap
340+ , benchIOSrc serially "concatMapPure1xN" Ops.concatMapPure1xN
341+ , benchIOSrc serially "concatMapNxN" Ops.concatMapNxN
342+ , benchIOSrc serially "concatMapRepl4xN" Ops.concatMapRepl4xN
340 ]
343 ]
341 -- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
344 -- scanl-map and foldl-map are equivalent to the scan and fold in the foldl
342 -- library. If scan/fold followed by a map is efficient enough we may not
345 -- library. If scan/fold followed by a map is efficient enough we may not
benchmark/LinearOps.hs+32−10
@@ -126,6 +126,15 @@ sourceUnfoldr n = S.unfoldr step n
126 then Nothing
126 then Nothing
127 else Just (cnt, cnt + 1)
127 else Just (cnt, cnt + 1)
128
128
129+{-# INLINE sourceUnfoldrN #-}
130+sourceUnfoldrN :: (Monad m, S.IsStream t) => Int -> Int -> t m Int
131+sourceUnfoldrN upto start = S.unfoldr step start
132+ where
133+ step cnt =
134+ if cnt > start + upto
135+ then Nothing
136+ else Just (cnt, cnt + 1)
137+
129{-# INLINE sourceUnfoldrM #-}
138{-# INLINE sourceUnfoldrM #-}
130sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> t m Int
139sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> t m Int
131sourceUnfoldrM n = S.unfoldrM step n
140sourceUnfoldrM n = S.unfoldrM step n
@@ -137,10 +146,10 @@ sourceUnfoldrM n = S.unfoldrM step n
137
146
138{-# INLINE sourceUnfoldrMN #-}
147{-# INLINE sourceUnfoldrMN #-}
139sourceUnfoldrMN :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
148sourceUnfoldrMN :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
140−sourceUnfoldrMN m n = S.unfoldrM step n
149+sourceUnfoldrMN upto start = S.unfoldrM step start
141 where
150 where
142 step cnt =
151 step cnt =
143− if cnt > n + m
152+ if cnt > start + upto
144 then return Nothing
153 then return Nothing
145 else return (Just (cnt, cnt + 1))
154 else return (Just (cnt, cnt + 1))
146
155
@@ -533,16 +542,29 @@ eqBy src = S.eqBy (==) src src
533cmpBy :: (Monad m, P.Ord a) => Stream m a -> m P.Ordering
542cmpBy :: (Monad m, P.Ord a) => Stream m a -> m P.Ordering
534cmpBy src = S.cmpBy P.compare src src
543cmpBy src = S.cmpBy P.compare src src
535
544
536−concatStreamLen, maxNested :: Int
545+-- The worst case for concatMap, concat a 1 element stream n times.
537−-- concatStreamLen = value2
538−-- maxNested = value2
539−concatStreamLen = 1
540−maxNested = 100000
541−
542{-# INLINE concatMap #-}
546{-# INLINE concatMap #-}
543concatMap :: S.MonadAsync m => Int -> Stream m Int
547concatMap :: S.MonadAsync m => Int -> Stream m Int
544−concatMap n = S.concatMap (\_ -> sourceUnfoldrMN maxNested n)
548+concatMap n = S.concatMap (\_ -> sourceUnfoldrMN 1 n)
545− (sourceUnfoldrMN concatStreamLen n)
549+ (sourceUnfoldrMN value n)
550+
551+{-# INLINE concatMapPure1xN #-}
552+concatMapPure1xN :: S.MonadAsync m => Int -> Stream m Int
553+concatMapPure1xN n = S.concatMap (\_ -> sourceUnfoldrN 1 n)
554+ (sourceUnfoldrN value n)
555+
556+-- We use a (sqrt n) element stream as source and then generate and concat a
557+-- (sqrt n) element stream for each element of the source to produce an n
558+-- element stream.
559+{-# INLINE concatMapNxN #-}
560+concatMapNxN :: S.MonadAsync m => Int -> Stream m Int
561+concatMapNxN n = S.concatMap (\_ -> sourceUnfoldrMN value2 n)
562+ (sourceUnfoldrMN value2 n)
563+
564+{-# INLINE concatMapRepl4xN #-}
565+concatMapRepl4xN :: S.MonadAsync m => Int -> Stream m Int
566+concatMapRepl4xN n = S.concatMap (S.replicate 4)
567+ (sourceUnfoldrMN (value `div` 4) n)
546
568
547-------------------------------------------------------------------------------
569-------------------------------------------------------------------------------
548-- Mixed Composition
570-- Mixed Composition
benchmark/StreamDOps.hs+4
@@ -266,6 +266,10 @@ cmpBy src = S.cmpBy P.compare src src
266zip :: Monad m => Stream m Int -> m ()
266zip :: Monad m => Stream m Int -> m ()
267zip src = transform $ S.zipWith (,) src src
267zip src = transform $ S.zipWith (,) src src
268
268
269+{-# INLINE concatMapRepl4xN #-}
270+concatMapRepl4xN :: Monad m => Stream m Int -> m ()
271+concatMapRepl4xN src = transform $ (S.concatMap (S.replicate 4) src)
272+
269-------------------------------------------------------------------------------
273-------------------------------------------------------------------------------
270-- Mixed Composition
274-- Mixed Composition
271-------------------------------------------------------------------------------
275-------------------------------------------------------------------------------
benchmark/StreamKOps.hs+6
@@ -225,6 +225,8 @@ dropAll n = composeN n $ S.drop maxValue
225dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
225dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
226dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
226dropWhileFalse n = composeN n $ S.dropWhile (<= 1)
227foldlS n = composeN n $ S.foldlS (flip S.cons) S.nil
227foldlS n = composeN n $ S.foldlS (flip S.cons) S.nil
228+-- We use a (sqrt n) element stream as source and then concat the same stream
229+-- for each element to produce an n element stream.
228concatMap n = composeN n $ (\s -> S.concatMap (\_ -> s) s)
230concatMap n = composeN n $ (\s -> S.concatMap (\_ -> s) s)
229intersperse n = composeN n $ S.intersperse maxValue
231intersperse n = composeN n $ S.intersperse maxValue
230
232
@@ -274,6 +276,10 @@ iterateDropWhileTrue = iterateSource (S.dropWhile (<= maxValue)) maxIters
274
276
275zip src = transform $ S.zipWith (,) src src
277zip src = transform $ S.zipWith (,) src src
276
278
279+{-# INLINE concatMapRepl4xN #-}
280+concatMapRepl4xN :: Monad m => Stream m Int -> m ()
281+concatMapRepl4xN src = transform $ (S.concatMap (S.replicate 4) src)
282+
277-------------------------------------------------------------------------------
283-------------------------------------------------------------------------------
278-- Mixed Composition
284-- Mixed Composition
279-------------------------------------------------------------------------------
285-------------------------------------------------------------------------------