2-- Module : Streamly.Benchmark.Data.ParserK
3-- Copyright : (c) 2020 Composewell Technologies
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
9{-# LANGUAGE FlexibleContexts #-}
10{-# OPTIONS_GHC -fspec-constr-recursive=4 #-}
17import Control.DeepSeq (NFData(..))
18import Control.Monad.Catch (MonadCatch)
19import Data.Foldable (asum)
20import System.Random (randomRIO)
21import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
23import qualified Control.Applicative as AP
24import qualified Data.Foldable as F
25import qualified Data.Traversable as TR
26import qualified Streamly.Prelude as S
27import qualified Streamly.Internal.Data.Fold as FL
28import qualified Streamly.Internal.Data.Parser.ParserK.Types as PR
29import qualified Streamly.Internal.Data.Parser.ParserD as PRD
30import qualified Streamly.Internal.Data.Stream.IsStream as IP
33import Streamly.Prelude (SerialT, MonadAsync, IsStream)
34import Streamly.Benchmark.Common
36-------------------------------------------------------------------------------
38-------------------------------------------------------------------------------
40-- XXX these can be moved to the common module
42{-# INLINE sourceUnfoldrM #-}
43sourceUnfoldrM :: (IsStream t, MonadAsync m) => Int -> Int -> t m Int
44sourceUnfoldrM value n = S.unfoldrM step n
49 else return (Just (cnt, cnt + 1))
51-- | Takes a fold method, and uses it with a default source.
52{-# INLINE benchIOSink #-}
54 :: (IsStream t, NFData b)
55 => Int -> String -> (t IO Int -> IO b) -> Benchmark
56benchIOSink value name f =
57 bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
59-------------------------------------------------------------------------------
61-------------------------------------------------------------------------------
64#define PARSE_OP (IP.parseD . PR.fromParserK)
66#define PARSE_OP IP.parseK
70satisfy :: MonadCatch m => (a -> Bool) -> PR.Parser m a a
71satisfy = PR.toParserK . PRD.satisfy
74any :: MonadCatch m => (a -> Bool) -> PR.Parser m a Bool
75any = PR.toParserK . PRD.any
78anyK :: (MonadCatch m, Ord a) => a -> SerialT m a -> m Bool
79anyK value = PARSE_OP (any (> value))
82all :: MonadCatch m => (a -> Bool) -> PR.Parser m a Bool
83all = PR.toParserK . PRD.all
86allK :: (MonadCatch m, Ord a) => a -> SerialT m a -> m Bool
87allK value = PARSE_OP (all (<= value))
90take :: MonadCatch m => Int -> PR.Parser m a ()
91take value = PR.toParserK $ PRD.take value FL.drain
94takeK :: MonadCatch m => Int -> SerialT m a -> m ()
95takeK value = PARSE_OP (take value)
97{-# INLINE takeWhile #-}
98takeWhile :: MonadCatch m => (a -> Bool) -> PR.Parser m a ()
99takeWhile p = PR.toParserK $ PRD.takeWhile p FL.drain
101{-# INLINE takeWhileK #-}
102takeWhileK :: MonadCatch m => Int -> SerialT m Int -> m ()
103takeWhileK value = PARSE_OP (takeWhile (<= value))
105{-# INLINE splitApp #-}
106splitApp :: MonadCatch m
107 => Int -> SerialT m Int -> m (Bool, Bool)
109 PARSE_OP ((,) <$> any (>= (value `div` 2)) <*> any (> value))
111{-# INLINE sequenceA #-}
112sequenceA :: MonadCatch m => Int -> SerialT m Int -> m Int
113sequenceA value xs = do
114 let parser = satisfy (> 0)
115 list = Prelude.replicate value parser
116 x <- PARSE_OP (TR.sequenceA list) xs
117 return $ Prelude.length x
119{-# INLINE sequenceA_ #-}
120sequenceA_ :: MonadCatch m => Int -> SerialT m Int -> m ()
121sequenceA_ value xs = do
122 let parser = satisfy (> 0)
123 list = Prelude.replicate value parser
124 PARSE_OP (F.sequenceA_ list) xs
126{-# INLINE sequence #-}
127sequence :: MonadCatch m => Int -> SerialT m Int -> m Int
128sequence value xs = do
129 let parser = satisfy (> 0)
130 list = Prelude.replicate value parser
131 x <- PARSE_OP (TR.sequence list) xs
132 return $ Prelude.length x
134{-# INLINE manyAlt #-}
135manyAlt :: MonadCatch m => SerialT m Int -> m Int
137 x <- PARSE_OP (AP.many (satisfy (> 0))) xs
138 return $ Prelude.length x
140{-# INLINE someAlt #-}
141someAlt :: MonadCatch m => SerialT m Int -> m Int
143 x <- PARSE_OP (AP.some (satisfy (> 0))) xs
144 return $ Prelude.length x
147choice :: MonadCatch m => Int -> SerialT m Int -> m Int
149 PARSE_OP (asum (replicate value (satisfy (< 0)))
150 AP.<|> satisfy (> 0))
152-------------------------------------------------------------------------------
154-------------------------------------------------------------------------------
157moduleName = "Data.Parser.ParserK"
159o_1_space_serial :: Int -> [Benchmark]
160o_1_space_serial value =
161 [ benchIOSink value "any" $ anyK value
162 , benchIOSink value "all" $ allK value
163 , benchIOSink value "take" $ takeK value
164 , benchIOSink value "takeWhile" $ takeWhileK value
165 , benchIOSink value "splitApp" $ splitApp value
168-- O(n) heap beacuse of accumulation of the list in strict IO monad?
169o_n_heap_serial :: Int -> [Benchmark]
170o_n_heap_serial value =
171 [ benchIOSink value "sequenceA" $ sequenceA value
172 , benchIOSink value "sequenceA_" $ sequenceA_ value
173 , benchIOSink value "sequence" $ sequence value
174 , benchIOSink value "manyAlt" manyAlt
175 , benchIOSink value "someAlt" someAlt
176 , benchIOSink value "choice" $ choice value
179-------------------------------------------------------------------------------
181-------------------------------------------------------------------------------
185 (value, cfg, benches) <- parseCLIOpts defaultStreamSize
186 value `seq` runMode (mode cfg) cfg benches (allBenchmarks value)
190 allBenchmarks value =
191 [ bgroup (o_1_space_prefix moduleName) $ concat
192 [ o_1_space_serial value
194 , bgroup (o_n_heap_prefix moduleName) $ concat
195 [ o_n_heap_serial value
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list