module Main (main) where
import Prelude ()
import Prelude.Compat
import Control.DeepSeq (force)
import Control.Exception (evaluate)
import Data.Aeson (Value (..), decode)
import Data.Foldable (toList)
import qualified Criterion.Main as C
import qualified Data.HashMap.Lazy as H
import qualified Data.ByteString.Lazy as BSL
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TLB
import qualified Text.PrettyPrint.Compact as PC
import qualified Text.PrettyPrint.HughesPJ as HPJ
import qualified Text.PrettyPrint.Leijen as WL
prettiestJSON :: Value -> PC.Doc ()
prettiestJSON (Bool True) = PC.text "true"
prettiestJSON (Bool False) = PC.text "false"
prettiestJSON (Object o) = PC.encloseSep (PC.text "{") (PC.text "}") (PC.text ",") (map prettyKV $ H.toList o)
where prettyKV (k,v) = PC.text (show k) PC.<> PC.text ":" PC.<+> prettiestJSON v
prettiestJSON (String s) = PC.string (show s)
prettiestJSON (Array a) = PC.encloseSep (PC.text "[") (PC.text "]") (PC.text ",") (map prettiestJSON $ toList a)
prettiestJSON Null = PC.mempty
prettiestJSON (Number n) = PC.text (show n)
pcRenderText :: Monoid a => PC.Doc a -> TL.Text
pcRenderText = TLB.toLazyText . PC.renderWith PC.defaultOptions
{ PC.optsAnnotate = \_ -> TLB.fromString }
wlJSON :: Value -> WL.Doc
wlJSON (Bool True) = WL.text "true"
wlJSON (Bool False) = WL.text "false"
wlJSON (Object o) = WL.encloseSep (WL.text "{") (WL.text "}") (WL.text ",") (map prettyKV $ H.toList o)
where prettyKV (k,v) = WL.text (show k) WL.<> WL.text ":" WL.<+> wlJSON v
wlJSON (String s) = WL.string (show s)
wlJSON (Array a) = WL.encloseSep (WL.text "[") (WL.text "]") (WL.text ",") (map wlJSON $ toList a)
wlJSON Null = WL.empty
wlJSON (Number n) = WL.text (show n)
wlRender :: WL.Doc -> String
wlRender d = WL.displayS (WL.renderPretty 1 80 d) ""
hpjEncloseSep :: HPJ.Doc -> HPJ.Doc -> HPJ.Doc -> [HPJ.Doc] -> HPJ.Doc
hpjEncloseSep open close sep list = open HPJ.<> HPJ.sep (HPJ.punctuate sep list) HPJ.<> close
hpjJSON :: Value -> HPJ.Doc
hpjJSON (Bool True) = HPJ.text "true"
hpjJSON (Bool False) = HPJ.text "false"
hpjJSON (Object o) = hpjEncloseSep (HPJ.text "{") (HPJ.text "}") (HPJ.text ",") (map prettyKV $ H.toList o)
where prettyKV (k,v) = HPJ.text (show k) HPJ.<> HPJ.text ":" HPJ.<+> hpjJSON v
hpjJSON (String s) = HPJ.text (show s)
hpjJSON (Array a) = hpjEncloseSep (HPJ.text "[") (HPJ.text "]") (HPJ.text ",") (map hpjJSON $ toList a)
hpjJSON Null = HPJ.empty
hpjJSON (Number n) = HPJ.text (show n)
readJSONValue :: FilePath -> IO Value
readJSONValue fname = do
contents <- BSL.readFile fname
let Just inpJson = decode contents
return inpJson
main :: IO ()
main = do
smallValue <- evaluate . force =<< readJSONValue "bench/small.json"
bigValue <- evaluate . force =<< readJSONValue "bench/big.json"
C.defaultMain
[ C.bgroup "small"
[ C.bench "pretty-compact" $ C.nf (PC.render . prettiestJSON) smallValue
, C.bench "pretty-compact Text" $ C.nf (pcRenderText . prettiestJSON) smallValue
, C.bench "pretty" $ C.nf (HPJ.render . hpjJSON) smallValue
, C.bench "wl-pprint" $ C.nf (wlRender . wlJSON) smallValue
]
, C.bgroup "big"
[ C.bench "pretty-compact" $ C.nf (PC.render . prettiestJSON) bigValue
, C.bench "pretty-compact Text" $ C.nf (pcRenderText . prettiestJSON) bigValue
, C.bench "pretty" $ C.nf (HPJ.render . hpjJSON) bigValue
, C.bench "wl-pprint" $ C.nf (wlRender . wlJSON) bigValue
]
]