on master help sign in
INLINE some/many implement *>/<*
d7866f7Harendra Kumar
benchmark/Streamly/Benchmark/Data/ParserD.hs+20−7
@@ -186,24 +186,31 @@ o_1_space_serial_parse value =
186 , benchIOSink value "split (all,any)" $ splitAllAny value
186 , benchIOSink value "split (all,any)" $ splitAllAny value
187 , benchIOSink value "many" many
187 , benchIOSink value "many" many
188 , benchIOSink value "some" some
188 , benchIOSink value "some" some
189− , benchIOSink value "choice/100" $ choice (value `div` 100)
190 , benchIOSink value "tee (all,any)" $ teeAllAny value
189 , benchIOSink value "tee (all,any)" $ teeAllAny value
191 , benchIOSink value "teeFst (all,any)" $ teeFstAllAny value
190 , benchIOSink value "teeFst (all,any)" $ teeFstAllAny value
192 , benchIOSink value "shortest (all,any)" $ shortestAllAny value
191 , benchIOSink value "shortest (all,any)" $ shortestAllAny value
193 , benchIOSink value "longest (all,any)" $ longestAllAny value
192 , benchIOSink value "longest (all,any)" $ longestAllAny value
194− , benchIOSink value "sequenceA/100" $ sequenceA (value `div` 100)
195− , benchIOSink value "sequenceA_/100" $ sequenceA_ (value `div` 100)
196− , benchIOSink value "sequence/100" $ sequence (value `div` 100)
197 ]
193 ]
198
194
199−o_1_heap_serial_parse :: Int -> [Benchmark]
195+-- These show non-linear time complexity
200−o_1_heap_serial_parse value =
196+-- Increase in rss is 20-40% on doubling the stream size
197+o_n_heap_serial_parse :: Int -> [Benchmark]
198+o_n_heap_serial_parse value =
201 [ benchIOSink value "lookAhead" $ lookAhead value
199 [ benchIOSink value "lookAhead" $ lookAhead value
202 , benchIOSink value "manyAlt" manyAlt
200 , benchIOSink value "manyAlt" manyAlt
203 , benchIOSink value "someAlt" someAlt
201 , benchIOSink value "someAlt" someAlt
204 , benchIOSink value "manyTill" $ manyTill value
202 , benchIOSink value "manyTill" $ manyTill value
205 ]
203 ]
206
204
205+-- accumulate results in a list in IO
206+o_n_space_serial_parse :: Int -> [Benchmark]
207+o_n_space_serial_parse value =
208+ [ benchIOSink value "sequenceA/100" $ sequenceA (value `div` 100)
209+ , benchIOSink value "sequenceA_/100" $ sequenceA_ (value `div` 100)
210+ , benchIOSink value "sequence/100" $ sequence (value `div` 100)
211+ , benchIOSink value "choice/100" $ choice (value `div` 100)
212+ ]
213+
207-------------------------------------------------------------------------------
214-------------------------------------------------------------------------------
208-- Driver
215-- Driver
209-------------------------------------------------------------------------------
216-------------------------------------------------------------------------------
@@ -225,7 +232,13 @@ main = do
225 , bgroup "o-n-heap"
232 , bgroup "o-n-heap"
226 [ bgroup "parser" $ concat
233 [ bgroup "parser" $ concat
227 [
234 [
228− o_1_heap_serial_parse value
235+ o_n_heap_serial_parse value
236+ ]
237+ ]
238+ , bgroup "o-n-space"
239+ [ bgroup "parser" $ concat
240+ [
241+ o_n_space_serial_parse value
229 ]
242 ]
230 ]
243 ]
231 ]
244 ]
benchmark/Streamly/Benchmark/Data/ParserK.hs+9
@@ -19,6 +19,7 @@ import System.Random (randomRIO)
19import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
19import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
20
20
21import qualified Control.Applicative as AP
21import qualified Control.Applicative as AP
22+import qualified Data.Foldable as F
22import qualified Data.Traversable as TR
23import qualified Data.Traversable as TR
23import qualified Streamly as S hiding (runStream)
24import qualified Streamly as S hiding (runStream)
24import qualified Streamly.Prelude as S
25import qualified Streamly.Prelude as S
@@ -83,6 +84,13 @@ sequenceA value xs = do
83 x <- IP.parseK (TR.sequenceA list) xs
84 x <- IP.parseK (TR.sequenceA list) xs
84 return $ Prelude.length x
85 return $ Prelude.length x
85
86
87+{-# INLINE sequenceA_ #-}
88+sequenceA_ :: MonadCatch m => Int -> SerialT m Int -> m ()
89+sequenceA_ value xs = do
90+ let parser = satisfy (> 0)
91+ list = Prelude.replicate value parser
92+ IP.parseK (F.sequenceA_ list) xs
93+
86{-# INLINE sequence #-}
94{-# INLINE sequence #-}
87sequence :: MonadCatch m => Int -> SerialT m Int -> m Int
95sequence :: MonadCatch m => Int -> SerialT m Int -> m Int
88sequence value xs = do
96sequence value xs = do
@@ -123,6 +131,7 @@ o_1_space_serial_parse value =
123o_n_heap_serial_parse :: Int -> [Benchmark]
131o_n_heap_serial_parse :: Int -> [Benchmark]
124o_n_heap_serial_parse value =
132o_n_heap_serial_parse value =
125 [ benchIOSink value "sequenceA" $ sequenceA value
133 [ benchIOSink value "sequenceA" $ sequenceA value
134+ , benchIOSink value "sequenceA_" $ sequenceA_ value
126 , benchIOSink value "sequence" $ sequence value
135 , benchIOSink value "sequence" $ sequence value
127 , benchIOSink value "manyAlt" manyAlt
136 , benchIOSink value "manyAlt" manyAlt
128 , benchIOSink value "someAlt" someAlt
137 , benchIOSink value "someAlt" someAlt
src/Streamly/Internal/Data/Parser/ParserK/Types.hs+35−3
@@ -58,7 +58,7 @@ yield b = MkParser (\_ yieldk -> yieldk (Z.nil, Right b))
58-------------------------------------------------------------------------------
58-------------------------------------------------------------------------------
59-- Sequential applicative
59-- Sequential applicative
60-------------------------------------------------------------------------------
60-------------------------------------------------------------------------------
61−--
61+
62-- | 'Applicative' form of 'Streamly.Internal.Data.Parser.splitWith'. Note that
62-- | 'Applicative' form of 'Streamly.Internal.Data.Parser.splitWith'. Note that
63-- this operation does not fuse, use 'Streamly.Internal.Data.Parser.splitWith'
63-- this operation does not fuse, use 'Streamly.Internal.Data.Parser.splitWith'
64-- when fusion is important.
64-- when fusion is important.
@@ -70,6 +70,20 @@ instance Monad m => Applicative (Parser m a) where
70 {-# INLINE (<*>) #-}
70 {-# INLINE (<*>) #-}
71 (<*>) = ap
71 (<*>) = ap
72
72
73+ {-# INLINE (*>) #-}
74+ m1 *> m2 = MkParser $ \inp yieldk ->
75+ let yield1 (z, b) = case b of
76+ Right _ -> runParser m2 z yieldk
77+ Left err -> runParser (die err) z yieldk
78+ in runParser m1 inp yield1
79+
80+ {-# INLINE (<*) #-}
81+ m1 <* m2 = MkParser $ \inp yieldk ->
82+ let yield1 (z, b) = case b of
83+ Right _ -> runParser m2 z (\(z1, _) -> yieldk (z1, b))
84+ Left err -> runParser (die err) z yieldk
85+ in runParser m1 inp yield1
86+
73-- | See 'Streamly.Internal.Data.Parser.die'.
87-- | See 'Streamly.Internal.Data.Parser.die'.
74--
88--
75-- /Internal/
89-- /Internal/
@@ -116,7 +130,7 @@ die err = MkParser (\z yieldk -> yieldk (z, Left err))
116-- Alpha x -> [x,x2]
130-- Alpha x -> [x,x2]
117-- @
131-- @
118--
132--
119−-- Seel also 'Streamly.Internal.Data.Parser.concatMap'. This monad instance
133+-- See also 'Streamly.Internal.Data.Parser.concatMap'. This monad instance
120-- does not fuse, use 'Streamly.Internal.Data.Parser.concatMap' when you need
134-- does not fuse, use 'Streamly.Internal.Data.Parser.concatMap' when you need
121-- fusion.
135-- fusion.
122--
136--
@@ -154,7 +168,25 @@ instance Monad m => Alternative (Parser m a) where
154 Right _ -> yieldk (Z.release z, b)
168 Right _ -> yieldk (Z.release z, b)
155 Left _ -> runParser m2 (Z.restore z) yieldk
169 Left _ -> runParser m2 (Z.restore z) yieldk
156 in runParser m1 (Z.checkpoint inp) yield1
170 in runParser m1 (Z.checkpoint inp) yield1
157− -- XXX INLINE some and many?
171+
172+ -- some and many are implemented here instead of using default definitions
173+ -- so that we can use INLINE on them. It gives 50% performance improvement.
174+
175+ {-# INLINE many #-}
176+ many v = many_v
177+
178+ where
179+
180+ many_v = some_v <|> pure []
181+ some_v = (:) <$> v <*> many_v
182+
183+ {-# INLINE some #-}
184+ some v = some_v
185+
186+ where
187+
188+ many_v = some_v <|> pure []
189+ some_v = (:) <$> v <*> many_v
158
190
159-- | 'mzero' is same as 'empty', it aborts the parser. 'mplus' is same as
191-- | 'mzero' is same as 'empty', it aborts the parser. 'mplus' is same as
160-- '<|>', it selects the first succeeding parser.
192-- '<|>', it selects the first succeeding parser.