on master help sign in
Add benchmarks for all types of continuation parsers
7f24c4dAdithya Kumar
benchmark/Streamly/Benchmark/Data/ParserK.hs+86−33
@@ -5,6 +5,10 @@
5-- License : BSD-3-Clause
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
6-- Maintainer : streamly@composewell.com
7
7
8+-- BENCH_CHUNKED -> fromParser
9+-- BENCH_CHUNKED_GENERIC -> fromParserGeneric
10+-- BENCH_SINGULAR -> fromParserSingular
11+
8{-# LANGUAGE CPP #-}
12{-# LANGUAGE CPP #-}
9{-# LANGUAGE FlexibleContexts #-}
13{-# LANGUAGE FlexibleContexts #-}
10{-# OPTIONS_GHC -Wno-orphans #-}
14{-# OPTIONS_GHC -Wno-orphans #-}
@@ -18,7 +22,13 @@ import Control.Applicative ((<|>))
18import Control.DeepSeq (NFData(..))
22import Control.DeepSeq (NFData(..))
19import Control.Monad.IO.Class (MonadIO)
23import Control.Monad.IO.Class (MonadIO)
20import Data.Foldable (asum)
24import Data.Foldable (asum)
25+#ifdef BENCH_CHUNKED
21import Streamly.Data.Array (Array, Unbox)
26import Streamly.Data.Array (Array, Unbox)
27+#endif
28+#ifdef BENCH_CHUNKED_GENERIC
29+import Streamly.Data.Array.Generic (Array)
30+import qualified Streamly.Internal.Data.Array.Generic as GenArr (chunksOf)
31+#endif
22import Streamly.Internal.Data.Fold (Fold(..))
32import Streamly.Internal.Data.Fold (Fold(..))
23import Streamly.Data.StreamK (StreamK)
33import Streamly.Data.StreamK (StreamK)
24import Streamly.Internal.Data.Parser
34import Streamly.Internal.Data.Parser
@@ -35,12 +45,52 @@ import qualified Streamly.Data.Stream as Stream
35import qualified Streamly.Data.Fold as FL
45import qualified Streamly.Data.Fold as FL
36import qualified Streamly.Internal.Data.Fold as Fold
46import qualified Streamly.Internal.Data.Fold as Fold
37import qualified Streamly.Data.Parser as PRD
47import qualified Streamly.Data.Parser as PRD
38−import qualified Streamly.Data.ParserK as PR
48+import qualified Streamly.Internal.Data.Parser.ParserK.Type as PR
39import qualified Streamly.Internal.Data.StreamK as StreamK
49import qualified Streamly.Internal.Data.StreamK as StreamK
40
50
41import Gauge
51import Gauge
42import Streamly.Benchmark.Common
52import Streamly.Benchmark.Common
43
53
54+-------------------------------------------------------------------------------
55+-- CPP Helpers
56+-------------------------------------------------------------------------------
57+
58+#ifdef BENCH_CHUNKED
59+
60+#define PARSE_OP StreamK.parseChunks
61+#define FROM_PARSER fromParser
62+#define INPUT (Array a)
63+#define PARSE_ELEM (Array Int)
64+#define CONSTRAINT_IO (MonadIO m, Unbox a)
65+#define CONSTRAINT (Monad m, Unbox a)
66+#define MODULE_NAME "ParserK.Chunked"
67+
68+#endif
69+
70+#ifdef BENCH_CHUNKED_GENERIC
71+
72+#define PARSE_OP StreamK.parseGenericChunks
73+#define FROM_PARSER fromParserGeneric
74+#define INPUT (Array a)
75+#define PARSE_ELEM (Array Int)
76+#define CONSTRAINT_IO (MonadIO m)
77+#define CONSTRAINT (Monad m)
78+#define MODULE_NAME "ParserK.Chunked.Generic"
79+
80+#endif
81+
82+#ifdef BENCH_SINGULAR
83+
84+#define PARSE_OP StreamK.parseSingular
85+#define FROM_PARSER fromParserSingular
86+#define INPUT a
87+#define PARSE_ELEM Int
88+#define CONSTRAINT_IO (MonadIO m)
89+#define CONSTRAINT (Monad m)
90+#define MODULE_NAME "ParserK.Singular"
91+
92+#endif
93+
44-------------------------------------------------------------------------------
94-------------------------------------------------------------------------------
45-- Utilities
95-- Utilities
46-------------------------------------------------------------------------------
96-------------------------------------------------------------------------------
@@ -60,49 +110,52 @@ sourceUnfoldrM value n = Stream.unfoldrM step n
60{-# INLINE benchIOSink #-}
110{-# INLINE benchIOSink #-}
61benchIOSink
111benchIOSink
62 :: NFData b
112 :: NFData b
63− => Int -> String -> (StreamK IO (Array Int) -> IO b) -> Benchmark
113+ => Int -> String -> (StreamK IO PARSE_ELEM -> IO b) -> Benchmark
64benchIOSink value name f =
114benchIOSink value name f =
65 bench name $ nfIO $ randomRIO (1,1)
115 bench name $ nfIO $ randomRIO (1,1)
66 >>= f
116 >>= f
67 . StreamK.fromStream
117 . StreamK.fromStream
118+#ifdef BENCH_CHUNKED
68 . Stream.chunksOf 4000
119 . Stream.chunksOf 4000
120+#endif
121+#ifdef BENCH_CHUNKED_GENERIC
122+ . GenArr.chunksOf 4000
123+#endif
69 . sourceUnfoldrM value
124 . sourceUnfoldrM value
70
125
71-------------------------------------------------------------------------------
126-------------------------------------------------------------------------------
72-- Parsers
127-- Parsers
73-------------------------------------------------------------------------------
128-------------------------------------------------------------------------------
74
129
75−#define PARSE_OP StreamK.parseChunks
76−
77{-# INLINE one #-}
130{-# INLINE one #-}
78one :: MonadIO m =>
131one :: MonadIO m =>
79− Int -> StreamK m (Array Int) -> m (Either ParseError (Maybe Int))
132+ Int -> StreamK m PARSE_ELEM -> m (Either ParseError (Maybe Int))
80−one value = StreamK.parseChunks p
133+one value = PARSE_OP p
81
134
82 where
135 where
83
136
84 p = do
137 p = do
85− m <- PR.fromFold FL.one
138+ m <- PR.FROM_PARSER (PRD.fromFold FL.one)
86 case m of
139 case m of
87 Just i -> if i >= value then pure m else p
140 Just i -> if i >= value then pure m else p
88 Nothing -> pure Nothing
141 Nothing -> pure Nothing
89
142
90{-# INLINE satisfy #-}
143{-# INLINE satisfy #-}
91−satisfy :: (MonadIO m, Unbox a) => (a -> Bool) -> PR.ParserK a m a
144+satisfy :: CONSTRAINT_IO => (a -> Bool) -> PR.ParserK INPUT m a
92−satisfy = PR.fromParser . PRD.satisfy
145+satisfy = PR.FROM_PARSER . PRD.satisfy
93
146
94{-# INLINE takeWhile #-}
147{-# INLINE takeWhile #-}
95−takeWhile :: (MonadIO m, Unbox a) => (a -> Bool) -> PR.ParserK a m ()
148+takeWhile :: CONSTRAINT_IO => (a -> Bool) -> PR.ParserK INPUT m ()
96−takeWhile p = PR.fromParser $ PRD.takeWhile p FL.drain
149+takeWhile p = PR.FROM_PARSER $ PRD.takeWhile p FL.drain
97
150
98{-# INLINE takeWhileK #-}
151{-# INLINE takeWhileK #-}
99takeWhileK :: MonadIO m =>
152takeWhileK :: MonadIO m =>
100− Int -> StreamK m (Array Int) -> m (Either ParseError ())
153+ Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
101takeWhileK value = PARSE_OP (takeWhile (<= value))
154takeWhileK value = PARSE_OP (takeWhile (<= value))
102
155
103{-# INLINE splitAp2 #-}
156{-# INLINE splitAp2 #-}
104splitAp2 :: MonadIO m
157splitAp2 :: MonadIO m
105− => Int -> StreamK m (Array Int) -> m (Either ParseError ((), ()))
158+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ((), ()))
106splitAp2 value =
159splitAp2 value =
107 PARSE_OP
160 PARSE_OP
108 ((,)
161 ((,)
@@ -112,7 +165,7 @@ splitAp2 value =
112
165
113{-# INLINE splitAp8 #-}
166{-# INLINE splitAp8 #-}
114splitAp8 :: MonadIO m
167splitAp8 :: MonadIO m
115− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
168+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
116splitAp8 value =
169splitAp8 value =
117 PARSE_OP
170 PARSE_OP
118 ( (\() () () () () () () () -> ())
171 ( (\() () () () () () () () -> ())
@@ -127,7 +180,7 @@ splitAp8 value =
127 )
180 )
128
181
129{-# INLINE sequenceA #-}
182{-# INLINE sequenceA #-}
130−sequenceA :: MonadIO m => Int -> StreamK m (Array Int) -> m Int
183+sequenceA :: MonadIO m => Int -> StreamK m PARSE_ELEM -> m Int
131sequenceA value xs = do
184sequenceA value xs = do
132 let parser = satisfy (> 0)
185 let parser = satisfy (> 0)
133 list = Prelude.replicate value parser
186 list = Prelude.replicate value parser
@@ -136,14 +189,14 @@ sequenceA value xs = do
136
189
137{-# INLINE sequenceA_ #-}
190{-# INLINE sequenceA_ #-}
138sequenceA_ :: MonadIO m =>
191sequenceA_ :: MonadIO m =>
139− Int -> StreamK m (Array Int) -> m (Either ParseError ())
192+ Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
140sequenceA_ value xs = do
193sequenceA_ value xs = do
141 let parser = satisfy (> 0)
194 let parser = satisfy (> 0)
142 list = Prelude.replicate value parser
195 list = Prelude.replicate value parser
143 PARSE_OP (F.sequenceA_ list) xs
196 PARSE_OP (F.sequenceA_ list) xs
144
197
145{-# INLINE sequence #-}
198{-# INLINE sequence #-}
146−sequence :: MonadIO m => Int -> StreamK m (Array Int) -> m Int
199+sequence :: MonadIO m => Int -> StreamK m PARSE_ELEM -> m Int
147sequence value xs = do
200sequence value xs = do
148 let parser = satisfy (> 0)
201 let parser = satisfy (> 0)
149 list = Prelude.replicate value parser
202 list = Prelude.replicate value parser
@@ -152,7 +205,7 @@ sequence value xs = do
152
205
153{-# INLINE sequence_ #-}
206{-# INLINE sequence_ #-}
154sequence_ :: MonadIO m =>
207sequence_ :: MonadIO m =>
155− Int -> StreamK m (Array Int) -> m (Either ParseError ())
208+ Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
156sequence_ value =
209sequence_ value =
157 let parser = satisfy (> 0)
210 let parser = satisfy (> 0)
158 list = Prelude.replicate value parser
211 list = Prelude.replicate value parser
@@ -184,13 +237,13 @@ takeWhileFailD predicate (Fold fstep finitial fextract) =
184 extract s = fmap (Done 0) (fextract s)
237 extract s = fmap (Done 0) (fextract s)
185
238
186{-# INLINE takeWhileFail #-}
239{-# INLINE takeWhileFail #-}
187−takeWhileFail :: (Monad m, Unbox a) =>
240+takeWhileFail :: CONSTRAINT =>
188− (a -> Bool) -> Fold m a b -> PR.ParserK a m b
241+ (a -> Bool) -> Fold m a b -> PR.ParserK INPUT m b
189−takeWhileFail p f = PR.fromParser (takeWhileFailD p f)
242+takeWhileFail p f = PR.FROM_PARSER (takeWhileFailD p f)
190
243
191{-# INLINE alt2 #-}
244{-# INLINE alt2 #-}
192alt2 :: MonadIO m
245alt2 :: MonadIO m
193− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
246+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
194alt2 value =
247alt2 value =
195 PARSE_OP
248 PARSE_OP
196 ( takeWhileFail (<= (value `div` 2)) Fold.drain
249 ( takeWhileFail (<= (value `div` 2)) Fold.drain
@@ -199,7 +252,7 @@ alt2 value =
199
252
200{-# INLINE alt8 #-}
253{-# INLINE alt8 #-}
201alt8 :: MonadIO m
254alt8 :: MonadIO m
202− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
255+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
203alt8 value =
256alt8 value =
204 PARSE_OP
257 PARSE_OP
205 ( takeWhileFail (<= ( value `div` 8)) Fold.drain
258 ( takeWhileFail (<= ( value `div` 8)) Fold.drain
@@ -214,7 +267,7 @@ alt8 value =
214
267
215{-# INLINE alt16 #-}
268{-# INLINE alt16 #-}
216alt16 :: MonadIO m
269alt16 :: MonadIO m
217− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
270+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
218alt16 value =
271alt16 value =
219 PARSE_OP
272 PARSE_OP
220 ( takeWhileFail (<= ( value `div` 16)) Fold.drain
273 ( takeWhileFail (<= ( value `div` 16)) Fold.drain
@@ -236,27 +289,27 @@ alt16 value =
236 )
289 )
237
290
238{-# INLINE manyAlt #-}
291{-# INLINE manyAlt #-}
239−manyAlt :: MonadIO m => StreamK m (Array Int) -> m Int
292+manyAlt :: MonadIO m => StreamK m PARSE_ELEM -> m Int
240manyAlt xs = do
293manyAlt xs = do
241 x <- PARSE_OP (AP.many (satisfy (> 0))) xs
294 x <- PARSE_OP (AP.many (satisfy (> 0))) xs
242 return $ Prelude.length x
295 return $ Prelude.length x
243
296
244{-# INLINE someAlt #-}
297{-# INLINE someAlt #-}
245−someAlt :: MonadIO m => StreamK m (Array Int) -> m Int
298+someAlt :: MonadIO m => StreamK m PARSE_ELEM -> m Int
246someAlt xs = do
299someAlt xs = do
247 x <- PARSE_OP (AP.some (satisfy (> 0))) xs
300 x <- PARSE_OP (AP.some (satisfy (> 0))) xs
248 return $ Prelude.length x
301 return $ Prelude.length x
249
302
250{-# INLINE choice #-}
303{-# INLINE choice #-}
251choice :: MonadIO m =>
304choice :: MonadIO m =>
252− Int -> StreamK m (Array Int) -> m (Either ParseError Int)
305+ Int -> StreamK m PARSE_ELEM -> m (Either ParseError Int)
253choice value =
306choice value =
254 PARSE_OP (asum (replicate value (satisfy (< 0)))
307 PARSE_OP (asum (replicate value (satisfy (< 0)))
255 AP.<|> satisfy (> 0))
308 AP.<|> satisfy (> 0))
256
309
257{-# INLINE monad2 #-}
310{-# INLINE monad2 #-}
258monad2 :: MonadIO m
311monad2 :: MonadIO m
259− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
312+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
260monad2 value =
313monad2 value =
261 PARSE_OP $ do
314 PARSE_OP $ do
262 takeWhile (<= (value `div` 2))
315 takeWhile (<= (value `div` 2))
@@ -264,7 +317,7 @@ monad2 value =
264
317
265{-# INLINE monad4 #-}
318{-# INLINE monad4 #-}
266monad4 :: MonadIO m
319monad4 :: MonadIO m
267− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
320+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
268monad4 value =
321monad4 value =
269 PARSE_OP $ do
322 PARSE_OP $ do
270 takeWhile (<= ( value `div` 4))
323 takeWhile (<= ( value `div` 4))
@@ -274,7 +327,7 @@ monad4 value =
274
327
275{-# INLINE monad8 #-}
328{-# INLINE monad8 #-}
276monad8 :: MonadIO m
329monad8 :: MonadIO m
277− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
330+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
278monad8 value =
331monad8 value =
279 PARSE_OP $ do
332 PARSE_OP $ do
280 takeWhile (<= ( value `div` 8))
333 takeWhile (<= ( value `div` 8))
@@ -288,7 +341,7 @@ monad8 value =
288
341
289{-# INLINE monad16 #-}
342{-# INLINE monad16 #-}
290monad16 :: MonadIO m
343monad16 :: MonadIO m
291− => Int -> StreamK m (Array Int) -> m (Either ParseError ())
344+ => Int -> StreamK m PARSE_ELEM -> m (Either ParseError ())
292monad16 value =
345monad16 value =
293 PARSE_OP $ do
346 PARSE_OP $ do
294 takeWhile (<= ( value `div` 16))
347 takeWhile (<= ( value `div` 16))
@@ -313,7 +366,7 @@ monad16 value =
313-------------------------------------------------------------------------------
366-------------------------------------------------------------------------------
314
367
315moduleName :: String
368moduleName :: String
316−moduleName = "Data.ParserK"
369+moduleName = MODULE_NAME
317
370
318instance NFData ParseError where
371instance NFData ParseError where
319 {-# INLINE rnf #-}
372 {-# INLINE rnf #-}
@@ -335,7 +388,7 @@ o_1_space_serial value =
335 ]
388 ]
336
389
337{-# INLINE sepBy1 #-}
390{-# INLINE sepBy1 #-}
338−sepBy1 :: MonadIO m => StreamK m (Array Int) -> m Int
391+sepBy1 :: MonadIO m => StreamK m PARSE_ELEM -> m Int
339sepBy1 xs = do
392sepBy1 xs = do
340 x <- PARSE_OP (parser (satisfy odd) (satisfy even)) xs
393 x <- PARSE_OP (parser (satisfy odd) (satisfy even)) xs
341 return $ Prelude.length x
394 return $ Prelude.length x
benchmark/streamly-benchmarks.cabal+25
@@ -415,10 +415,35 @@ benchmark Data.Parser
415 else
415 else
416 ghc-options: +RTS -M2000M -RTS
416 ghc-options: +RTS -M2000M -RTS
417
417
418+benchmark Data.ParserK.Singular
419+ import: bench-options
420+ type: exitcode-stdio-1.0
421+ hs-source-dirs: Streamly/Benchmark/Data
422+ cpp-options: -DBENCH_SINGULAR
423+ main-is: ParserK.hs
424+ if impl(ghcjs)
425+ buildable: False
426+ else
427+ buildable: True
428+ build-depends: exceptions >= 0.8 && < 0.11
429+
418benchmark Data.ParserK
430benchmark Data.ParserK
419 import: bench-options
431 import: bench-options
420 type: exitcode-stdio-1.0
432 type: exitcode-stdio-1.0
421 hs-source-dirs: Streamly/Benchmark/Data
433 hs-source-dirs: Streamly/Benchmark/Data
434+ cpp-options: -DBENCH_CHUNKED
435+ main-is: ParserK.hs
436+ if impl(ghcjs)
437+ buildable: False
438+ else
439+ buildable: True
440+ build-depends: exceptions >= 0.8 && < 0.11
441+
442+benchmark Data.ParserK.Generic
443+ import: bench-options
444+ type: exitcode-stdio-1.0
445+ hs-source-dirs: Streamly/Benchmark/Data
446+ cpp-options: -DBENCH_CHUNKED_GENERIC
422 main-is: ParserK.hs
447 main-is: ParserK.hs
423 if impl(ghcjs)
448 if impl(ghcjs)
424 buildable: False
449 buildable: False