on master help sign in
Use zipWith from StreamD in zipAsyncWith etc.

Improves perf of zipAsyncWith by 4x and applicative ZipAsync by 2x. Not sure why applicative does not show the same perf as zipAsyncWith.

commite16a980c5fb74202ccef7c6cab6dd2f27eb5a045 authorHarendra Kumar <harendra.kumar@gmail.com> dateThu 21 Nov 2019, 21:31 (7 years ago) parent36bfc45
2 files changed+38−43
src/Streamly/Internal/Prelude.hs+31−5 src/Streamly/Streams/Zip.hs+7−38
src/Streamly/Internal/Prelude.hs+31−5
@@ -248,8 +248,8 @@ module Streamly.Internal.Prelude
248248 -- ** Zipping
249249 , zipWith
250250 , zipWithM
251− , Z.zipAsyncWith
252− , Z.zipAsyncWithM
251+ , zipAsyncWith
252+ , zipAsyncWithM
253253
254254 -- ** Nested Streams
255255 , concatMapM
@@ -435,7 +435,7 @@ import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
435435import Streamly.Internal.Data.Unfold.Types (Unfold)
436436import Streamly.Internal.Memory.Array.Types (Array, writeNUnsafe)
437437-- import Streamly.Memory.Ring (Ring)
438−import Streamly.Internal.Data.SVar (MonadAsync, defState)
438+import Streamly.Internal.Data.SVar (MonadAsync, defState, adaptState)
439439import Streamly.Streams.Async (mkAsync')
440440import Streamly.Streams.Combinators (inspectMode, maxYields)
441441import Streamly.Streams.Prelude
@@ -456,11 +456,9 @@ import qualified Streamly.Internal.Data.Fold.Types as FL
456456import qualified Streamly.Streams.Prelude as P
457457import qualified Streamly.Streams.StreamK as K
458458import qualified Streamly.Streams.StreamD as D
459−import qualified Streamly.Streams.Zip as Z
460459
461460#ifdef USE_STREAMK_ONLY
462461import qualified Streamly.Streams.StreamK as S
463−import qualified Streamly.Streams.Zip as S
464462#else
465463import qualified Streamly.Streams.StreamD as S
466464#endif
@@ -2034,6 +2032,34 @@ zipWithM f m1 m2 = fromStreamS $ S.zipWithM f (toStreamS m1) (toStreamS m2)
20342032zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
20352033zipWith f m1 m2 = fromStreamS $ S.zipWith f (toStreamS m1) (toStreamS m2)
20362034
2035+------------------------------------------------------------------------------
2036+-- Parallel Zipping
2037+------------------------------------------------------------------------------
2038+
2039+-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
2040+-- are generated concurrently.
2041+--
2042+-- @since 0.1.0
2043+{-# INLINE zipAsyncWith #-}
2044+zipAsyncWith :: (IsStream t, MonadAsync m)
2045+ => (a -> b -> c) -> t m a -> t m b -> t m c
2046+zipAsyncWith f m1 m2 = K.mkStream $ \st stp sng yld -> do
2047+ ma <- Par.mkParallel (adaptState st) m1
2048+ mb <- Par.mkParallel (adaptState st) m2
2049+ K.foldStream st stp sng yld $ zipWith f ma mb
2050+
2051+-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
2052+-- are generated concurrently.
2053+--
2054+-- @since 0.4.0
2055+{-# INLINABLE zipAsyncWithM #-}
2056+zipAsyncWithM :: (IsStream t, MonadAsync m)
2057+ => (a -> b -> m c) -> t m a -> t m b -> t m c
2058+zipAsyncWithM f m1 m2 = K.mkStream $ \st stp sng yld -> do
2059+ ma <- Par.mkParallel (adaptState st) m1
2060+ mb <- Par.mkParallel (adaptState st) m2
2061+ K.foldStream st stp sng yld $ zipWithM f ma mb
2062+
20372063------------------------------------------------------------------------------
20382064-- Comparison
20392065------------------------------------------------------------------------------
src/Streamly/Streams/Zip.hs+7−38
@@ -20,12 +20,7 @@
2020--
2121module Streamly.Streams.Zip
2222 (
23− K.zipWith
24− , K.zipWithM
25− , zipAsyncWith
26− , zipAsyncWithM
27−
28− , ZipSerialM
23+ ZipSerialM
2924 , ZipSerial
3025 , ZipStream -- deprecated
3126 , zipSerially
@@ -53,10 +48,10 @@ import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
5348 readListPrecDefault)
5449import Prelude hiding (map, repeat, zipWith)
5550
56−import Streamly.Streams.StreamK (IsStream(..), Stream, mkStream, foldStream)
57−import Streamly.Streams.Parallel (mkParallel)
51+import Streamly.Streams.StreamK (IsStream(..), Stream)
5852import Streamly.Streams.Serial (map)
59−import Streamly.Internal.Data.SVar (MonadAsync, adaptState)
53+import Streamly.Internal.Data.SVar (MonadAsync)
54+import Streamly.Internal.Prelude (zipWith, zipAsyncWith)
6055
6156import qualified Streamly.Streams.Prelude as P
6257import qualified Streamly.Streams.StreamK as K
@@ -136,39 +131,12 @@ instance Monad m => Functor (ZipSerialM m) where
136131
137132instance Monad m => Applicative (ZipSerialM m) where
138133 pure = ZipSerialM . K.repeat
139− (<*>) = K.zipWith id
134+ {-# INLINE (<*>) #-}
135+ (<*>) = zipWith id
140136
141137FOLDABLE_INSTANCE(ZipSerialM)
142138TRAVERSABLE_INSTANCE(ZipSerialM)
143139
144−------------------------------------------------------------------------------
145−-- Parallel Zipping
146−------------------------------------------------------------------------------
147−
148−-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
149−-- are generated concurrently.
150−--
151−-- @since 0.1.0
152−{-# INLINABLE zipAsyncWith #-}
153−zipAsyncWith :: (IsStream t, MonadAsync m)
154− => (a -> b -> c) -> t m a -> t m b -> t m c
155−zipAsyncWith f m1 m2 = mkStream $ \st stp sng yld -> do
156− ma <- mkParallel (adaptState st) m1
157− mb <- mkParallel (adaptState st) m2
158− foldStream st stp sng yld (K.zipWith f ma mb)
159−
160−-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
161−-- are generated concurrently.
162−--
163−-- @since 0.4.0
164−{-# INLINABLE zipAsyncWithM #-}
165−zipAsyncWithM :: (IsStream t, MonadAsync m)
166− => (a -> b -> m c) -> t m a -> t m b -> t m c
167−zipAsyncWithM f m1 m2 = mkStream $ \st stp sng yld -> do
168− ma <- mkParallel (adaptState st) m1
169− mb <- mkParallel (adaptState st) m2
170− foldStream st stp sng yld (K.zipWithM f ma mb)
171−
172140------------------------------------------------------------------------------
173141-- Parallely Zipping Streams
174142------------------------------------------------------------------------------
@@ -233,4 +201,5 @@ instance Monad m => Functor (ZipAsyncM m) where
233201
234202instance MonadAsync m => Applicative (ZipAsyncM m) where
235203 pure = ZipAsyncM . K.repeat
204+ {-# INLINE (<*>) #-}
236205 m1 <*> m2 = zipAsyncWith id m1 m2