77-- |
88-- | This benchmark suite also compares parsers to equivalent Regex. This
99-- | provides an answer to the common question “How much slower is this package
10- -- | than Regex?” Answer: approximately 100 ×. The Regex benchmarks also give
10+ -- | than Regex?” Answer: approximately 10 ×. The Regex benchmarks also give
1111-- | us a rough way to calibrate benchmarks run on different platforms.
1212-- |
1313-- | `--expose-gc` is from
@@ -55,10 +55,11 @@ import Prelude
5555
5656import Bench.Json.Parsing as BenchParsing
5757import Bench.Json.StringParser as BenchStringParser
58- import Bench.Json.TestData (largeJson , mediumJson , smallJson )
59- import Control.Monad.Trampoline (runTrampoline )
58+ import Bench.Json.TestData (largeJson , mediumJson )
6059import Control.Monad.Free (liftF )
60+ import Control.Monad.Trampoline (runTrampoline )
6161import Data.Array (fold , replicate )
62+ import Data.Array as Array
6263import Data.Either (either )
6364import Data.List (many , manyRec )
6465import Data.List.Types (List )
@@ -69,37 +70,35 @@ import Effect (Effect)
6970import Effect.Console (log )
7071import Effect.Exception (throw )
7172import Effect.Unsafe (unsafePerformEffect )
72- import Performance.Minibench (benchWith )
7373import Parsing (Parser , runParser , runParserT )
74- import Parsing.String (string )
74+ import Parsing.Combinators (chainl , chainlRec , chainr , chainrRec , manyTill , manyTillRec , manyTillRec_ , manyTill_ , sepBy , sepByRec )
75+ import Parsing.String (anyChar , char , string )
7576import Parsing.String.Basic (digit )
77+ import Performance.Minibench (benchWith )
7678import StringParser as StringParser
7779import StringParser.CodePoints as StringParser.CodePoints
7880import StringParser.CodeUnits as StringParser.CodeUnits
7981
8082string23 :: String
8183string23 = " 23"
8284
83- string23_2 :: String
84- string23_2 = fold $ replicate 2 string23
85-
86- -- string23_10000 :: String
87- -- string23_10000 = fold $ replicate 10000 string23
85+ string23_10000 :: String
86+ string23_10000 = fold $ replicate 5000 string23
8887
89- string23_500 :: String
90- string23_500 = fold $ replicate 500 string23
88+ string23_10000x :: String
89+ string23_10000x = string23_10000 <> " x "
9190
92- stringSkidoo :: String
93- stringSkidoo = " skidoo "
91+ string23_1000 :: String
92+ string23_1000 = fold $ replicate 500 string23
9493
95- stringSkidoo_2 :: String
96- stringSkidoo_2 = fold $ replicate 2 stringSkidoo
94+ string23_1000x :: String
95+ string23_1000x = string23_1000 <> " x "
9796
98- -- stringSkidoo_10000 :: String
99- -- stringSkidoo_10000 = fold $ replicate 10000 stringSkidoo
97+ stringSkidoo :: String
98+ stringSkidoo = " skidoooooo "
10099
101- stringSkidoo_1000 :: String
102- stringSkidoo_1000 = fold $ replicate 1000 stringSkidoo
100+ stringSkidoo_100000 :: String
101+ stringSkidoo_100000 = fold $ replicate 10000 stringSkidoo
103102
104103parse23 :: Parser String (List Char )
105104parse23 = many digit
@@ -132,14 +131,14 @@ pattern23 = either (unsafePerformEffect <<< throw) identity
132131 }
133132
134133parseSkidoo :: Parser String (List String )
135- parseSkidoo = many $ string " skidoo "
134+ parseSkidoo = many $ string " skidoooooo "
136135
137136parseSkidooRec :: Parser String (List String )
138- parseSkidooRec = manyRec $ string " skidoo "
137+ parseSkidooRec = manyRec $ string " skidoooooo "
139138
140139patternSkidoo :: Regex
141140patternSkidoo = either (unsafePerformEffect <<< throw) identity
142- $ regex " skidoo "
141+ $ regex " skidoooooo "
143142 $ RegexFlags
144143 { dotAll: true
145144 , global: true
@@ -161,38 +160,109 @@ htmlTableWrap caption benchmark = do
161160main :: Effect Unit
162161main = do
163162 log " <tr>"
164- htmlTableWrap " runParser parse23" $ benchWith 200
165- $ \_ -> runParser string23_500 parse23
166- htmlTableWrap " StringParser.runParser parse23Points" $ benchWith 20
167- $ \_ -> StringParser .runParser parse23Points string23_500
168- htmlTableWrap " StringParser.runParser parse23Units" $ benchWith 200
169- $ \_ -> StringParser .runParser parse23Units string23_500
170- htmlTableWrap " runParser parse23Rec" $ benchWith 200
171- $ \_ -> runParser string23_500 parse23Rec
172- htmlTableWrap " StringParser.runParser parse23PointsRec" $ benchWith 20
173- $ \_ -> StringParser .runParser parse23PointsRec string23_500
174- htmlTableWrap " StringParser.runParser parse23UnitsRec" $ benchWith 200
175- $ \_ -> StringParser .runParser parse23UnitsRec string23_500
176- htmlTableWrap " Regex.match pattern23" $ benchWith 200
177- $ \_ -> Regex .match pattern23 string23_500
178- htmlTableWrap " runParser parseSkidoo" $ benchWith 200
179- $ \_ -> runParser stringSkidoo_1000 parseSkidoo
180- htmlTableWrap " runParser parseSkidooRec" $ benchWith 200
181- $ \_ -> runParser stringSkidoo_1000 parseSkidooRec
182- htmlTableWrap " Regex.match patternSkidoo" $ benchWith 200
183- $ \_ -> Regex .match patternSkidoo stringSkidoo_1000
184- htmlTableWrap " runParser json smallJson" $ benchWith 1000
185- $ \_ -> runParser smallJson BenchParsing .json
186- htmlTableWrap " runTrampoline runParser json smallJson" $ benchWith 1000
187- $ \_ -> runTrampoline $ runParserT smallJson BenchParsing .json
188- htmlTableWrap " StringParser.runParser json smallJson" $ benchWith 500
189- $ \_ -> StringParser .runParser BenchStringParser .json smallJson
163+
164+ -- These inputs are too small for good measurement, but larger ones blow stack
165+ -- log "<th><h2>digit 1000</h2></th>"
166+ -- htmlTableWrap "runParser many digit 1000" $ benchWith 200
167+ -- $ \_ -> runParser string23_1000 parse23
168+ -- htmlTableWrap "StringParser many CodePoints.anyDigit 1000" $ benchWith 20
169+ -- $ \_ -> StringParser.runParser parse23Points string23_1000
170+ -- htmlTableWrap "StringParser many CodeUnits.anyDigit 1000" $ benchWith 200
171+ -- $ \_ -> StringParser.runParser parse23Units string23_1000
172+ -- htmlTableWrap "runParser manyRec digit 1000" $ benchWith 200
173+ -- $ \_ -> runParser string23_1000 parse23Rec
174+ -- htmlTableWrap "StringParser manyRec CodePoints.anyDigit 1000" $ benchWith 20
175+ -- $ \_ -> StringParser.runParser parse23PointsRec string23_1000
176+ -- htmlTableWrap "StringParser manyRec CodeUnits.anyDigit 1000" $ benchWith 200
177+ -- $ \_ -> StringParser.runParser parse23UnitsRec string23_1000
178+ -- htmlTableWrap "Regex.match \\d* 1000" $ benchWith 200
179+ -- $ \_ -> Regex.match pattern23 string23_1000
180+
181+ log " <th><h2>digit 10000</h2></th>"
182+ htmlTableWrap " runParser many digit 10000" $ benchWith 50
183+ $ \_ -> runParser string23_10000 parse23
184+ htmlTableWrap " runParser manyRec digit 10000" $ benchWith 50
185+ $ \_ -> runParser string23_10000 parse23Rec
186+ htmlTableWrap " runParser Array.many digit 10000" $ benchWith 50
187+ $ \_ -> runParser string23_10000 (Array .many digit)
188+ htmlTableWrap " StringParser manyRec CodePoints.anyDigit 10000" $ benchWith 20
189+ $ \_ -> StringParser .runParser parse23PointsRec string23_10000
190+ htmlTableWrap " StringParser manyRec CodeUnits.anyDigit 10000" $ benchWith 200
191+ $ \_ -> StringParser .runParser parse23UnitsRec string23_10000
192+ htmlTableWrap " Regex.match \\ d* 10000" $ benchWith 200
193+ $ \_ -> Regex .match pattern23 string23_10000
194+
195+ log " <th><h2>string 100000</h2></th>"
196+ htmlTableWrap " runParser many string" $ benchWith 200
197+ $ \_ -> runParser stringSkidoo_100000 parseSkidoo
198+ htmlTableWrap " runParser manyRec string" $ benchWith 200
199+ $ \_ -> runParser stringSkidoo_100000 parseSkidooRec
200+ htmlTableWrap " Regex.match literal*" $ benchWith 200
201+ $ \_ -> Regex .match patternSkidoo stringSkidoo_100000
202+
203+ log " <th><h2>sepBy 1000</h2></th>"
204+ htmlTableWrap " runParser sepBy 1000" $ benchWith 50
205+ $ \_ -> runParser string23_1000 $ sepBy anyChar (char ' 3' )
206+ htmlTableWrap " runParser sepByRec 1000" $ benchWith 50
207+ $ \_ -> runParser string23_1000 $ sepByRec anyChar (char ' 3' )
208+
209+ log " <th><h2>sepBy 10000</h2></th>"
210+ -- sepBy not stack-safe
211+ -- htmlTableWrap "runParser sepBy 10000" $ benchWith 50
212+ -- $ \_ -> runParser string23_10000 $ sepBy anyChar (char '3')
213+ htmlTableWrap " runParser sepByRec 10000" $ benchWith 50
214+ $ \_ -> runParser string23_10000 $ sepByRec anyChar (char ' 3' )
215+
216+ log " <th><h2>chainl 10000</h2></th>"
217+ htmlTableWrap " runParser chainl 10000" $ benchWith 50
218+ $ \_ -> runParser string23_10000 $ chainl anyChar (pure const) ' x'
219+ htmlTableWrap " runParser chainlRec 10000" $ benchWith 50
220+ $ \_ -> runParser string23_10000 $ chainlRec anyChar (pure const) ' x'
221+
222+ log " <th><h2>chainr 1000</h2></th>"
223+ htmlTableWrap " runParser chainr 1000" $ benchWith 5
224+ $ \_ -> runParser string23_1000 $ chainr anyChar (pure const) ' x'
225+ htmlTableWrap " runParser chainrRec 1000" $ benchWith 5
226+ $ \_ -> runParser string23_1000 $ chainrRec anyChar (pure const) ' x'
227+
228+ log " <th><h2>chainr 10000</h2></th>"
229+ -- chainr not stack-safe
230+ -- htmlTableWrap "runParser chainr 10000" $ benchWith 5
231+ -- $ \_ -> runParser string23_10000 $ chainr anyChar (pure const) 'x'
232+ htmlTableWrap " runParser chainrRec 10000" $ benchWith 5
233+ $ \_ -> runParser string23_10000 $ chainrRec anyChar (pure const) ' x'
234+
235+ log " <th><h2>manyTill 1000</h2></th>"
236+ htmlTableWrap " runParser manyTill 1000" $ benchWith 50
237+ $ \_ -> runParser string23_1000x $ manyTill anyChar (char ' x' )
238+ htmlTableWrap " runParser manyTillRec 1000" $ benchWith 50
239+ $ \_ -> runParser string23_1000x $ manyTillRec anyChar (char ' x' )
240+ htmlTableWrap " runParser manyTill_ 1000" $ benchWith 50
241+ $ \_ -> runParser string23_1000x $ manyTill_ anyChar (char ' x' )
242+ htmlTableWrap " runParser manyTillRec_ 1000" $ benchWith 50
243+ $ \_ -> runParser string23_1000x $ manyTillRec_ anyChar (char ' x' )
244+
245+ log " <th><h2>manyTill 10000</h2></th>"
246+ -- manyTill not stack-safe
247+ -- htmlTableWrap "runParser manyTill 10000" $ benchWith 50
248+ -- $ \_ -> runParser string23_10000x $ manyTill anyChar (char 'x')
249+ htmlTableWrap " runParser manyTillRec 10000" $ benchWith 50
250+ $ \_ -> runParser string23_10000x $ manyTillRec anyChar (char ' x' )
251+ -- manyTill_ not stack-safe
252+ -- htmlTableWrap "runParser manyTill_ 10000" $ benchWith 50
253+ -- $ \_ -> runParser string23_10000x $ manyTill_ anyChar (char 'x')
254+ htmlTableWrap " runParser manyTillRec_ 10000" $ benchWith 50
255+ $ \_ -> runParser string23_10000x $ manyTillRec_ anyChar (char ' x' )
256+
257+ log " <th><h2>mediumJson</h2></th>"
190258 htmlTableWrap " runParser json mediumJson" $ benchWith 500
191259 $ \_ -> runParser mediumJson BenchParsing .json
192260 htmlTableWrap " runTrampoline runParser json mediumJson" $ benchWith 500
193261 $ \_ -> runTrampoline $ runParserT mediumJson BenchParsing .json
194262 htmlTableWrap " StringParser.runParser json mediumJson" $ benchWith 1000
195263 $ \_ -> StringParser .runParser BenchStringParser .json mediumJson
264+
265+ log " <th><h2>largeJson</h2></th>"
196266 htmlTableWrap " runParser json largeJson" $ benchWith 100
197267 $ \_ -> runParser largeJson BenchParsing .json
198268 htmlTableWrap " runTrampoline runParser json largeJson" $ benchWith 100
0 commit comments