markup-parse 0.1.1 → 0.1.1.1
raw patch · 7 files changed
+239/−480 lines, 7 filesdep +doctest-paralleldep −html-parsedep −optparse-applicativedep −perfdep ~basedep ~containersPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: doctest-parallel
Dependencies removed: html-parse, optparse-applicative, perf, text
Dependency ranges changed: base, containers
API changes (from Hackage documentation)
- MarkupParse: data Tree a
+ MarkupParse: data () => Tree a
- MarkupParse.FlatParse: data Result e a
+ MarkupParse.FlatParse: data () => Result e a
Files
- app/speed.hs +0/−204
- markup-parse.cabal +21/−79
- readme.md +210/−0
- readme.org +0/−196
- src/MarkupParse.hs +1/−1
- src/MarkupParse/FlatParse.hs +1/−0
- test/doctests.hs +6/−0
− app/speed.hs
@@ -1,204 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}---- | basic measurement and callibration-module Main where--import Data.ByteString qualified as B-import Data.Text.IO qualified as Text-import FlatParse.Basic (byteStringOf, char, satisfy, skipMany)-import FlatParse.Basic qualified as FP-import MarkupParse-import MarkupParse.FlatParse-import Options.Applicative as OA-import Perf-import Text.HTML.Parser qualified as HP-import Text.HTML.Tree qualified as HP-import Prelude--data RunType = RunDefault | RunReduced | RunMarkup | RunWhitespace | RunWrappedQ | RunIsa | RunByteStringOf deriving (Eq, Show)--data SpeedOptions = SpeedOptions- { speedReportOptions :: ReportOptions,- speedRunType :: RunType,- speedFile :: FilePath,- speedSnippet :: B.ByteString- }- deriving (Eq, Show)--parseRun :: OA.Parser RunType-parseRun =- flag' RunDefault (long "default" <> help "run default performance test")- <|> flag' RunMarkup (long "markup" <> short 'm' <> help "run markup performance test")- <|> flag' RunWhitespace (long "whitespace" <> help "run whitespace parsing test")- <|> flag' RunWrappedQ (long "wrappedQ" <> help "run wrappedQ parsing test")- <|> flag' RunReduced (long "reduced" <> help "run with reduced result sizes")- <|> flag' RunByteStringOf (long "bytestringof" <> help "test bytestringof")- <|> flag' RunIsa (long "isa" <> help "test isa")- <|> pure RunDefault--speedOptions :: OA.Parser SpeedOptions-speedOptions =- SpeedOptions- <$> parseReportOptions- <*> parseRun- <*> strOption (value "other/line.svg" <> long "file" <> short 'f' <> help "file to test")- <*> strOption (value "'wrapped'" <> long "snippet" <> help "snippet to parse")--speedInfo :: ParserInfo SpeedOptions-speedInfo =- info- (speedOptions <**> helper)- (fullDesc <> progDesc "markup-parse benchmarking" <> header "speed tests")--main :: IO ()-main = do- o <- execParser speedInfo- let rep = speedReportOptions o- let r = speedRunType o- let f = speedFile o- let snip = speedSnippet o-- case r of- RunDefault -> do- bs <- B.readFile f- t <- Text.readFile f-- reportMainWith rep (show r) $ do- ts' <- ffap "html-parse tokens" HP.parseTokens t- _ <- ffap "html-parse tree" (either undefined id . HP.tokensToForest) ts'- tsHtml <-- warnError- <$> ffap "tokenize" (tokenize Xml) bs- _ <-- warnError- <$> ffap "gather" (gather Xml) tsHtml- m <-- warnError- <$> ffap "markup" (markup Xml) bs- _ <- ffap "normalize" normalize m- _ <- ffap "markdown" (markdown Compact Xml) m- pure ()- RunMarkup -> do- bs <- B.readFile f- reportMainWith rep (show r) $ do- fap "markup" (length . elements . markup_ Xml) bs- RunWhitespace -> do- reportMainWith rep (show r) (wsFap " \n\nx")- RunWrappedQ -> do- reportMainWith rep (show r) (fapWrappedQ snip)- RunIsa -> do- reportMainWith rep (show r) fapIsa- RunByteStringOf -> do- reportMainWith rep (show r) fapBSOf- RunReduced -> do- bs <- B.readFile f- t <- Text.readFile f- let ts' = HP.parseTokens t- let ts = tokenize_ Xml bs- let m = markup_ Xml bs- reportMainWith rep (show r) $ do- _ <- ffap "html-parse tokens" (length . HP.parseTokens) t- _ <- ffap "html-parse tree" (either undefined length . HP.tokensToForest) ts'- _ <- ffap "tokenize" (length . tokenize Xml) bs- _ <- ffap "gather" (length . elements . gather_ Xml) ts- _ <- ffap "markup" (length . elements . markup_ Xml) bs- _ <- ffap "normalize" normalize m- _ <- ffap "markdown" (markdown Compact Xml) m- pure ()---- | Consume whitespace.-wsSwitch_ :: FP.Parser e ()-wsSwitch_ =- $( FP.switch- [|- case _ of- " " -> wsSwitch_- "\n" -> wsSwitch_- "\t" -> wsSwitch_- "\r" -> wsSwitch_- "\f" -> wsSwitch_- _ -> pure ()- |]- )---- | consume whitespace-wsSatisfy_ :: FP.Parser e ()-wsSatisfy_ = FP.skipMany (FP.satisfy isWhitespace)---- | consume whitespace-wsFusedSatisfy_ :: FP.Parser e ()-wsFusedSatisfy_ = FP.skipMany (FP.fusedSatisfy isWhitespace (const False) (const False) (const False)) >> pure ()---- | consume whitespace-wsSatisfyAscii_ :: FP.Parser e ()-wsSatisfyAscii_ = FP.skipMany (FP.satisfyAscii isWhitespace) >> pure ()--wsFap :: B.ByteString -> PerfT IO [[Double]] ()-wsFap bs = do- fap "wsFusedSatisfy_" (FP.runParser wsFusedSatisfy_) bs- fap "ws" (FP.runParser ws) bs- fap "wss" (FP.runParser wss) bs- fap "ws_" (FP.runParser ws_) bs- fap "wsSwitch_" (FP.runParser wsSwitch_) bs- fap "wsSatisfy_" (FP.runParser wsSatisfy_) bs- fap "wsSatisfyAscii_" (FP.runParser wsSatisfyAscii_) bs- pure ()--fapWrappedQ :: B.ByteString -> PerfT IO [[Double]] ()-fapWrappedQ bs = do- fap "wrappedQ" (FP.runParser wrappedQ) bs- fap "wrappedQSatisfy" (FP.runParser wrappedQSatisfy) bs- fap "wrappedQSkipSatisfy" (FP.runParser wrappedQSkipSatisfy) bs- fap "wrappedQNotA" (FP.runParser wrappedQNotA) bs- fap "wrappedQCandidate" (FP.runParser wrappedQCandidate) bs- pure ()--fapIsa :: PerfT IO [[Double]] ()-fapIsa = do- fap "isa isAttrName" (FP.runParser (isa isAttrName)) "name"- fap "attrNameP" (FP.runParser attrNameP) "name"- pure ()--fapBSOf :: PerfT IO [[Double]] ()-fapBSOf = do- fap "byteStringOf" (FP.runParser (byteStringOf (attrsP Html))) " a=\"a\" b=b c>"- fap "byteStringOf'" (FP.runParser (byteStringOf' (attrsP Html))) " a=\"a\" b=b c>"- pure ()--isAttrName :: Char -> Bool-isAttrName x =- not $- isWhitespace x- || (x == '/')- || (x == '>')- || (x == '=')--attrNameP :: FP.Parser e B.ByteString-attrNameP = byteStringOf $ some (satisfy isAttrName)--wrappedQSatisfy :: FP.Parser e B.ByteString-wrappedQSatisfy =- ($(char '"') *> (byteStringOf $ many (satisfy (/= '"'))) <* $(char '"'))- <|> ($(char '\'') *> (byteStringOf $ many (satisfy (/= '\''))) <* $(char '\''))--wrappedQSkipSatisfy :: FP.Parser e B.ByteString-wrappedQSkipSatisfy =- ($(char '"') *> (byteStringOf $ skipMany (satisfy (/= '"'))) <* $(char '"'))- <|> ($(char '\'') *> (byteStringOf $ skipMany (satisfy (/= '\''))) <* $(char '\''))--wrappedQNotA :: FP.Parser e B.ByteString-wrappedQNotA =- ($(char '"') *> nota '"' <* $(char '"'))- <|> ($(char '\'') *> nota '\'' <* $(char '\''))--wrappedQCandidate :: FP.Parser e B.ByteString-wrappedQCandidate =- wrappedSQ' <|> wrappedDQ'--wrappedSQ' :: FP.Parser b B.ByteString-wrappedSQ' = $(char '\'') *> nota '\'' <* $(char '\'')--wrappedDQ' :: FP.Parser b B.ByteString-wrappedDQ' = $(char '"') *> nota '"' <* $(char '"')
markup-parse.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: markup-parse-version: 0.1.1+version: 0.1.1.1 license: BSD-3-Clause license-file: LICENSE copyright: Copyright, Tony Day, 2023-@@ -13,12 +13,15 @@ description: A markup parser and printer, from and to strict bytestrings, optimised for speed. build-type: Simple-tested-with: GHC == 9.6.2+tested-with:+ , GHC == 9.10.1+ , GHC == 9.6.5+ , GHC == 9.8.2 extra-doc-files: ChangeLog.md other/*.html other/*.svg- readme.org+ readme.md source-repository head type: git@@ -40,69 +43,16 @@ -Wredundant-constraints common ghc2021-stanza- if impl ( ghc >= 9.2 )- default-language: GHC2021-- if impl ( ghc < 9.2 )- default-language: Haskell2010- default-extensions:- BangPatterns- BinaryLiterals- ConstrainedClassMethods- ConstraintKinds- DeriveDataTypeable- DeriveFoldable- DeriveFunctor- DeriveGeneric- DeriveLift- DeriveTraversable- DoAndIfThenElse- EmptyCase- EmptyDataDecls- EmptyDataDeriving- ExistentialQuantification- ExplicitForAll- FlexibleContexts- FlexibleInstances- ForeignFunctionInterface- GADTSyntax- GeneralisedNewtypeDeriving- HexFloatLiterals- ImplicitPrelude- InstanceSigs- KindSignatures- MonomorphismRestriction- MultiParamTypeClasses- NamedFieldPuns- NamedWildCards- NumericUnderscores- PatternGuards- PolyKinds- PostfixOperators- RankNTypes- RelaxedPolyRec- ScopedTypeVariables- StandaloneDeriving- StarIsType- TraditionalRecordSyntax- TupleSections- TypeApplications- TypeOperators- TypeSynonymInstances-- if impl ( ghc < 9.2 ) && impl ( ghc >= 8.10 )- default-extensions:- ImportQualifiedPost- StandaloneKindSignatures+ default-language: GHC2021 library import: ghc-options-stanza import: ghc2021-stanza hs-source-dirs: src build-depends:- , base >=4.7 && <5+ , base >=4.14 && <5 , bytestring >=0.11.3 && <0.13- , containers >=0.6 && <0.7+ , containers >=0.6 && <0.8 , deepseq >=1.4.4 && <1.6 , flatparse >=0.3.5 && <0.6 , string-interpolate >=0.3 && <0.4@@ -115,6 +65,16 @@ MarkupParse.FlatParse MarkupParse.Patch +test-suite doctests+ import: ghc2021-stanza+ main-is: doctests.hs+ hs-source-dirs: test+ build-depends:+ , base >=4.14 && <5+ , doctest-parallel >=0.3 && <0.4+ ghc-options: -threaded+ type: exitcode-stdio-1.0+ test-suite markup-parse-diff import: ghc-options-exe-stanza import: ghc-options-stanza@@ -122,29 +82,11 @@ main-is: diff.hs hs-source-dirs: app build-depends:- , base >=4.7 && <5+ , base >=4.14 && <5 , bytestring >=0.11.3 && <0.13 , markup-parse , string-interpolate >=0.3 && <0.4- , tasty >=1.2 && <1.5+ , tasty >=1.2 && <1.6 , tasty-golden >=2.3.1.1 && <2.4 , tree-diff >=0.3 && <0.4- type: exitcode-stdio-1.0--benchmark markup-parse-speed- import: ghc-options-exe-stanza- import: ghc-options-stanza- import: ghc2021-stanza- main-is: speed.hs- hs-source-dirs: app- build-depends:- , base >=4.7 && <5- , bytestring >=0.11.3 && <0.13- , flatparse >=0.3.5 && <0.6- , html-parse >=0.2 && <0.3- , markup-parse- , optparse-applicative >=0.17 && <0.19- , perf >=0.12 && <0.13- , text >=1.2 && <2.2- ghc-options: -O2 type: exitcode-stdio-1.0
+ readme.md view
@@ -0,0 +1,210 @@++# Table of Contents++1. [markup-parse](#org813b686)+2. [Development](#org3d7b96c)+3. [Main Pipeline types](#orgb8f20ca)+4. [MarkupParse.Patch](#org3c16287)+5. [wiki diff test debug](#org25edc96)+6. [Reference](#org4a018da)+ 1. [Prior Art](#org1ed6bdf)+7. [Performance](#org9b10723)+ 1. [Profiling](#orgf660933)+++<a id="org813b686"></a>++# markup-parse++[](https://hackage.haskell.org/package/markup-parse)+[](https://github.com/tonyday567/markup-parse/actions?query=workflow%3Ahaskell-ci)++`markup-parse` parses and prints a subset of common XML & HTML structured data, from and to strict bytestrings+++<a id="org3d7b96c"></a>++# Development++ :r+ :set prompt "> "+ :set -Wno-type-defaults+ :set -Wno-name-shadowing+ :set -XOverloadedStrings+ :set -XTemplateHaskell+ :set -XQuasiQuotes+ import Control.Monad+ import MarkupParse+ import MarkupParse.FlatParse+ import MarkupParse.Patch+ import Data.ByteString qualified as B+ import Data.ByteString.Char8 qualified as C+ import Data.Map.Strict qualified as Map+ import Data.Function+ import FlatParse.Basic hiding (take)+ import Data.String.Interpolate+ import Data.TreeDiff+ import Control.Monad+ bs <- B.readFile "other/line.svg"+ C.length bs++ Preprocessing library for markup-parse-0.1.1..+ GHCi, version 9.6.2: https://www.haskell.org/ghc/ :? for help+ [1 of 3] Compiling MarkupParse.FlatParse ( src/MarkupParse/FlatParse.hs, interpreted )+ [2 of 3] Compiling MarkupParse ( src/MarkupParse.hs, interpreted )+ [3 of 3] Compiling MarkupParse.Patch ( src/MarkupParse/Patch.hs, interpreted )+ Ok, three modules loaded.+ g+ Ok, three modules loaded.+ 7554+++<a id="orgb8f20ca"></a>++# Main Pipeline types++ :t tokenize Html+ :t gather Html+ :t normalize+ :t degather+ :t detokenize Html+ :t tokenize Html >=> gather Html >=> (normalize >>> pure) >=> degather Html >=> (fmap (detokenize Html) >>> pure)++ tokenize Html :: ByteString -> Warn [Token]+ gather Html :: [Token] -> Warn Markup+ normalize :: Markup -> Markup+ degather :: Standard -> Markup -> Warn [Token]+ detokenize Html :: Token -> ByteString+ tokenize Html >=> gather Html >=> (normalize >>> pure) >=> degather Html >=> (fmap (detokenize Html) >>> pure)+ :: ByteString -> These [MarkupWarning] [ByteString]++Round trip equality++ m = markup_ Xml bs+ m == (markup_ Xml $ markdown_ Compact Xml m)++ True+++<a id="org3c16287"></a>++# MarkupParse.Patch++Obviously, patch doesn’t belong here long-term but has been very useful in testing and development.++ showPatch $ patch [1, 2, 3, 5] [0, 1, 2, 4, 6]++ [+0, -3, +4, -5, +6]+++<a id="org25edc96"></a>++# wiki diff test debug++ bs <- B.readFile "other/Parsing - Wikipedia.html"+ m = markup_ Html bs+ m == (markup_ Html $ markdown_ Compact Html m)++ True+++<a id="org4a018da"></a>++# Reference++[HTML Standard](https://html.spec.whatwg.org/#toc-syntax)++[Are (non-void) self-closing tags valid in HTML5? - Stack Overflow](https://stackoverflow.com/questions/3558119/are-non-void-self-closing-tags-valid-in-html5)++[Extensible Markup Language (XML) 1.0 (Fifth Edition)](https://www.w3.org/TR/xml/)+++<a id="org1ed6bdf"></a>++## Prior Art++[html-parse](https://hackage.haskell.org/package/html-parse) is an attoparsec-based parser for HTML. The HTML parsing here has referenced this parsing logic for HTML elements.++[blaze-markup](https://hackage.haskell.org/package/blaze-markup) & [lucid](https://hackage.haskell.org/package/lucid) are HTML DSLs and printers, but not parsers.++[xeno](https://hackage.haskell.org/package/xeno) is an “event-based” XML parser with a more complicated base markup type.++[XMLParser](https://hackage.haskell.org/package/XMLParser) & [hexml](https://hackage.haskell.org/package/hexml) are parsec-based parsers.+++<a id="org9b10723"></a>++# Performance++The [perf](https://hackage.haskell.org/package/perf) library has been used to measure performance of the library.++\`cabal bench\` runs the default benchmarking:++ cabal bench++ Running 1 benchmarks...+ Benchmark markup-parse-speed: RUNNING...+ label1 label2 old result new result change+ + gather time 9.33e4 7.73e4 improvement+ html-parse tokenstime 1.21e6 1.17e6+ html-parse tree time 6.61e4 7.59e4 slightly-degraded+ markdown time 3.75e5 3.92e5+ markup time 4.72e5 5.20e5 slightly-degraded+ normalize time 2.80e5 3.04e5 slightly-degraded+ tokenize time 8.59e5 8.67e5+ Benchmark markup-parse-speed: FINISH+++<a id="orgf660933"></a>++## Profiling++Profiling is used to aid library development:++ cabal configure --enable-library-profiling --enable-executable-profiling -fprof-auto -fprof --write-ghc-environment-files=always --enable-benchmarks -O2++cabal.project.local++ write-ghc-environment-files: always+ ignore-project: False+ flags: +prof +prof-auto+ library-profiling: True+ executable-profiling: True++Profiling slow the main functions significantly:++ ./app/speed -n 1000 --best -c +RTS -s -p -hc -l -RTS+ label1 label2 old_result new_result status+ + gather time 2.08e4 3.01e4 degraded+ html-parse tokens time 4.70e5 1.72e6 degraded+ html-parse tree time 2.30e4 3.85e4 degraded+ markdown time 3.51e5 5.70e5 degraded+ markup time 2.10e5 1.05e6 degraded+ normalize time 8.43e4 1.90e5 degraded+ tokenize time 1.94e5 1.02e6 degraded+ 4,520,989,296 bytes allocated in the heap+ 2,668,887,592 bytes copied during GC+ 287,122,272 bytes maximum residency (21 sample(s))+ 1,572,000 bytes maximum slop+ 560 MiB total memory in use (0 MiB lost due to fragmentation)+ + Tot time (elapsed) Avg pause Max pause+ Gen 0 1073 colls, 0 par 0.471s 0.479s 0.0004s 0.0024s+ Gen 1 21 colls, 0 par 2.428s 2.575s 0.1226s 0.3303s+ + INIT time 0.007s ( 0.008s elapsed)+ MUT time 2.142s ( 1.945s elapsed)+ GC time 1.904s ( 2.071s elapsed)+ RP time 0.000s ( 0.000s elapsed)+ PROF time 0.995s ( 0.982s elapsed)+ EXIT time 0.026s ( 0.000s elapsed)+ Total time 5.074s ( 5.006s elapsed)+ + %GC time 0.0% (0.0% elapsed)+ + Alloc rate 2,110,654,040 bytes per MUT second+ + Productivity 61.8% of total user, 58.5% of total elapsed+
− readme.org
@@ -1,196 +0,0 @@-* markup-parse--[[https://hackage.haskell.org/package/markup-parse][https://img.shields.io/hackage/v/markup-parse.svg]]-[[https://github.com/tonyday567/markup-parse/actions?query=workflow%3Ahaskell-ci][https://github.com/tonyday567/markup-parse/workflows/haskell-ci/badge.svg]]--~markup-parse~ parses and prints a subset of common XML & HTML structured data, from and to strict bytestrings--* Development--#+begin_src haskell :results output :exports both-:r-:set prompt "> "-:set -Wno-type-defaults-:set -Wno-name-shadowing-:set -XOverloadedStrings-:set -XTemplateHaskell-:set -XQuasiQuotes-import Control.Monad-import MarkupParse-import MarkupParse.FlatParse-import MarkupParse.Patch-import Data.ByteString qualified as B-import Data.ByteString.Char8 qualified as C-import Data.Map.Strict qualified as Map-import Data.Function-import FlatParse.Basic hiding (take)-import Data.String.Interpolate-import Data.TreeDiff-import Control.Monad-bs <- B.readFile "other/line.svg"-C.length bs-#+end_src--#+RESULTS:-: Preprocessing library for markup-parse-0.1.1..-: GHCi, version 9.6.2: https://www.haskell.org/ghc/ :? for help-: [1 of 3] Compiling MarkupParse.FlatParse ( src/MarkupParse/FlatParse.hs, interpreted )-: [2 of 3] Compiling MarkupParse ( src/MarkupParse.hs, interpreted )-: [3 of 3] Compiling MarkupParse.Patch ( src/MarkupParse/Patch.hs, interpreted )-: Ok, three modules loaded.-: g-: Ok, three modules loaded.-: 7554--* Main Pipeline types--#+begin_src haskell :results output :exports both-:t tokenize Html-:t gather Html-:t normalize-:t degather-:t detokenize Html-:t tokenize Html >=> gather Html >=> (normalize >>> pure) >=> degather Html >=> (fmap (detokenize Html) >>> pure)-#+end_src--#+RESULTS:-: tokenize Html :: ByteString -> Warn [Token]-: gather Html :: [Token] -> Warn Markup-: normalize :: Markup -> Markup-: degather :: Standard -> Markup -> Warn [Token]-: detokenize Html :: Token -> ByteString-: tokenize Html >=> gather Html >=> (normalize >>> pure) >=> degather Html >=> (fmap (detokenize Html) >>> pure)-: :: ByteString -> These [MarkupWarning] [ByteString]--Round trip equality--#+begin_src haskell :results output :exports both-m = markup_ Xml bs-m == (markup_ Xml $ markdown_ Compact Xml m)-#+end_src--#+RESULTS:-: True--* MarkupParse.Patch--Obviously, patch doesn't belong here long-term but has been very useful in testing and development.--#+begin_src haskell :results output :exports both-showPatch $ patch [1, 2, 3, 5] [0, 1, 2, 4, 6]-#+end_src--#+RESULTS:-: [+0, -3, +4, -5, +6]--* wiki diff test debug--#+begin_src haskell :results output :exports both-bs <- B.readFile "other/Parsing - Wikipedia.html"-m = markup_ Html bs-m == (markup_ Html $ markdown_ Compact Html m)-#+end_src--#+RESULTS:-: True--* Reference--[[https://html.spec.whatwg.org/#toc-syntax][HTML Standard]]--[[https://stackoverflow.com/questions/3558119/are-non-void-self-closing-tags-valid-in-html5][Are (non-void) self-closing tags valid in HTML5? - Stack Overflow]]--[[https://www.w3.org/TR/xml/][Extensible Markup Language (XML) 1.0 (Fifth Edition)]]--** Prior Art--[[https://hackage.haskell.org/package/html-parse][html-parse]] is an attoparsec-based parser for HTML. The HTML parsing here has referenced this parsing logic for HTML elements.--[[https://hackage.haskell.org/package/blaze-markup][blaze-markup]] & [[https://hackage.haskell.org/package/lucid][lucid]] are HTML DSLs and printers, but not parsers.--[[https://hackage.haskell.org/package/xeno][xeno]] is an "event-based" XML parser with a more complicated base markup type.--[[https://hackage.haskell.org/package/XMLParser][XMLParser]] & [[https://hackage.haskell.org/package/hexml][hexml]] are parsec-based parsers.--* Performance--The [[https://hackage.haskell.org/package/perf][perf]] library has been used to measure performance of the library.--`cabal bench` runs the default benchmarking:--#+begin_src sh :results output :exports both-cabal bench-#+end_src--#+RESULTS:-#+begin_example-Running 1 benchmarks...-Benchmark markup-parse-speed: RUNNING...-label1 label2 old result new result change--gather time 9.33e4 7.73e4 improvement-html-parse tokenstime 1.21e6 1.17e6-html-parse tree time 6.61e4 7.59e4 slightly-degraded-markdown time 3.75e5 3.92e5-markup time 4.72e5 5.20e5 slightly-degraded-normalize time 2.80e5 3.04e5 slightly-degraded-tokenize time 8.59e5 8.67e5-Benchmark markup-parse-speed: FINISH-#+end_example--** Profiling--Profiling is used to aid library development:--#+begin_src sh :results output-cabal configure --enable-library-profiling --enable-executable-profiling -fprof-auto -fprof --write-ghc-environment-files=always --enable-benchmarks -O2-#+end_src--cabal.project.local--#+begin_example-write-ghc-environment-files: always-ignore-project: False-flags: +prof +prof-auto-library-profiling: True-executable-profiling: True-#+end_example--Profiling slow the main functions significantly:--#+begin_example-./app/speed -n 1000 --best -c +RTS -s -p -hc -l -RTS-label1 label2 old_result new_result status--gather time 2.08e4 3.01e4 degraded-html-parse tokens time 4.70e5 1.72e6 degraded-html-parse tree time 2.30e4 3.85e4 degraded-markdown time 3.51e5 5.70e5 degraded-markup time 2.10e5 1.05e6 degraded-normalize time 8.43e4 1.90e5 degraded-tokenize time 1.94e5 1.02e6 degraded- 4,520,989,296 bytes allocated in the heap- 2,668,887,592 bytes copied during GC- 287,122,272 bytes maximum residency (21 sample(s))- 1,572,000 bytes maximum slop- 560 MiB total memory in use (0 MiB lost due to fragmentation)-- Tot time (elapsed) Avg pause Max pause- Gen 0 1073 colls, 0 par 0.471s 0.479s 0.0004s 0.0024s- Gen 1 21 colls, 0 par 2.428s 2.575s 0.1226s 0.3303s-- INIT time 0.007s ( 0.008s elapsed)- MUT time 2.142s ( 1.945s elapsed)- GC time 1.904s ( 2.071s elapsed)- RP time 0.000s ( 0.000s elapsed)- PROF time 0.995s ( 0.982s elapsed)- EXIT time 0.026s ( 0.000s elapsed)- Total time 5.074s ( 5.006s elapsed)-- %GC time 0.0% (0.0% elapsed)-- Alloc rate 2,110,654,040 bytes per MUT second-- Productivity 61.8% of total user, 58.5% of total elapsed-#+end_example-
src/MarkupParse.hs view
@@ -457,7 +457,7 @@ -- Markup {elements = [Node {rootLabel = Content "<content>", subForest = []}]} -- -- >>> markup_ Html $ markdown_ Compact Html $ contentRaw "<content>"--- *** Exception: UnclosedTag+-- Markup {elements = *** Exception: UnclosedTag -- ... contentRaw :: ByteString -> Markup contentRaw bs = Markup [pure $ Content bs]
src/MarkupParse/FlatParse.hs view
@@ -57,6 +57,7 @@ -- $setup -- >>> :set -XTemplateHaskell+-- >>> :set -XOverloadedStrings -- >>> import MarkupParse.FlatParse -- >>> import FlatParse.Basic
+ test/doctests.hs view
@@ -0,0 +1,6 @@+import System.Environment (getArgs)+import Test.DocTest (mainFromCabal)+import Prelude (IO, (=<<))++main :: IO ()+main = mainFromCabal "markup-parse" =<< getArgs