packages feed

type-of-html-1.5.0.0: bench/Perf.hs

{-# OPTIONS_GHC -freduction-depth=0 #-}

{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE DataKinds        #-}

module Main where

import Html
import qualified Html.Attribute as A
import qualified Blaze          as BL
import qualified Small          as S
import qualified Medium         as M
import qualified Big            as B

import Criterion.Main
import Data.String
import System.Random
import System.IO.Unsafe
import Data.Proxy
import Text.Blaze.Html.Renderer.Utf8
import Data.Semigroup ((<>))
import qualified Data.Text.Lazy   as LT
import qualified Data.Text        as T

main :: IO ()
main = defaultMain
  [ small
  , medium
  , big
  , comparison
  , scaling
  ]

small :: Benchmark
small = bgroup "Small"
  [ bench "oneElement"                   $ nf (renderByteString . S.oneElement) ""
  , bench "nestedElement"                $ nf (renderByteString . S.nestedElement) ""
  , bench "parallelElement"              $ nf (renderByteString . S.parallelElement) ""
  , bench "listElement"                  $ nf (renderByteString . S.listElement) ""
  , bench "Int"                          $ nf renderByteString (123456789 :: Int)
  , bench "Integer"                      $ nf renderByteString (123456789 :: Integer)
  , bench "Double"                       $ nf renderByteString (123456789 :: Double)
  , bench "Float"                        $ nf renderByteString (123456789 :: Float)
  , bench "Word"                         $ nf renderByteString (123456789 :: Word)
  , bench "Proxy"                        $ nf renderByteString (Proxy :: Proxy "abc")
  , bench "Char"                         $ nf renderByteString 'a'
  , bench "oneElement Proxy"             $ nf (renderByteString . S.oneElement) (Proxy :: Proxy "abc")
  , bench "()"                           $ nf renderByteString ()
  , bench "oneElement ()"                $ nf (renderByteString . S.oneElement) ()
  , bench "oneAttribute"                 $ nf (renderByteString . A.class_) ""
  , bench "oneAttribute ()"              $ nf (renderByteString . A.class_)  ()
  , bench "oneAttribute Proxy"           $ nf (renderByteString . A.class_)  (Proxy :: Proxy "abc")
  , bench "parallelAttribute"            $ nf (\x -> renderByteString $ A.class_ x # A.id_ x) ""
  , bench "elementWithAttribute"         $ nf (\x -> renderByteString $ div_A (A.class_ x) x) ""
  , bench "elementWithParallelAttribute" $ nf (\x -> renderByteString $ div_A (A.class_ x # A.id_ x) x) ""
  , bench "listOfAttributes"             $ nf (\x -> renderByteString [A.class_ x, A.class_ x]) ""
  , bench "listOfListOf"                 $ nf (\x -> renderByteString $ div_ [i_ [span_ x]]) ""
  ]

medium :: Benchmark
medium = bgroup "Medium"
  [ bench "helloWorld"          $ nf (renderByteString . M.helloWorld) "medium"
  , bench "randomString"        $ nf renderByteString randomString
  , bench "randomStringRaw"     $ nf renderByteString randomStringRaw
  , bench "randomStrictText"    $ nf renderByteString randomStrictText
  , bench "randomStrictTextRaw" $ nf renderByteString randomStrictTextRaw
  , bench "randomLazyText"      $ nf renderByteString randomLazyText
  , bench "randomLazyTextRaw"   $ nf renderByteString randomLazyTextRaw
  , bench "table"               $ nf (renderByteString . M.table) (2,2)
  , bench "page"                $ nf (renderByteString . M.page) "medium"
  , bench "pageA"               $ nf (renderByteString . M.pageA) "medium"
  , bench "attrShort"           $ nf (renderByteString . M.attrShort) "medium"
  , bench "attrLong"            $ nf (renderByteString . M.attrLong) "medium"
  ]

{-# NOINLINE randomString #-}
randomString :: String
randomString = unsafePerformIO $ take 250 . randoms <$> newStdGen

{-# NOINLINE randomStringRaw #-}
randomStringRaw :: Raw String
randomStringRaw = unsafePerformIO $ Raw . take 250 . randoms <$> newStdGen

{-# NOINLINE randomStrictText #-}
randomStrictText :: T.Text
randomStrictText = unsafePerformIO $ T.pack . take 250 . randoms <$> newStdGen

{-# NOINLINE randomStrictTextRaw #-}
randomStrictTextRaw :: Raw T.Text
randomStrictTextRaw = unsafePerformIO $ Raw . T.pack . take 250 . randoms <$> newStdGen

{-# NOINLINE randomLazyText #-}
randomLazyText :: LT.Text
randomLazyText = unsafePerformIO $ LT.pack . take 250 . randoms <$> newStdGen

{-# NOINLINE randomLazyTextRaw #-}
randomLazyTextRaw :: Raw LT.Text
randomLazyTextRaw = unsafePerformIO $ Raw . LT.pack . take 250 . randoms <$> newStdGen

big :: Benchmark
big = bgroup "Big"
  [ bench "table"  $ nf (renderByteString . M.table) (15,15)
  , bench "page"   $ nf (renderByteString . B.page) "big"
  ]

comparison :: Benchmark
comparison = bgroup "Comparison"
  [ bgroup "hello world"
    [ bench "blaze-html"   $ nf (renderHtml . BL.blazeHelloWorld) (fromString "TEST")
    , bench "type-of-html" $ nf (renderByteString . M.helloWorld) "TEST"
    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ M.helloWorld (V @ "x"))) (Put "TEST")
    ]
  , bgroup "table"
    [ bench "blaze-html"   $ nf (renderHtml . BL.blazeTable) (4,4)
    , bench "type-of-html" $ nf (renderByteString . M.table) (4,4)
    ]
  , bgroup "small page"
    [ bench "blaze-html"   $ nf (renderHtml . BL.blazePageA) (fromString "TEST")
    , bench "type-of-html" $ nf (renderByteString . M.pageA) "TEST"
    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ M.pageA (V @ "x"))) (Put "TEST")
    ]
  , bgroup "medium page"
    [ bench "blaze-html"   $ nf (renderHtml . (\x -> BL.blazePageA x <> BL.blazePageA x)) (fromString "TEST")
    , bench "type-of-html" $ nf (renderByteString . (\x -> M.pageA x # M.pageA x)) "TEST"
    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ M.pageA (V @ "x") # M.pageA (V @ "x"))) (Put "TEST")
    ]
  , bgroup "big page"
    [ bench "blaze-html"   $ nf (renderHtml . (\x -> BL.blazePageA x <> BL.blazePageA x <> BL.blazePageA x <> BL.blazePageA x)) (fromString "TEST")
    , bench "type-of-html" $ nf (renderByteString . (\x -> M.pageA x # M.pageA x # M.pageA x # M.pageA x)) "TEST"
    , bench "compactHTML"  $ nf (renderCompactByteString (compactHTML $ M.pageA (V @ "x") # M.pageA (V @ "x") # M.pageA (V @ "x") # M.pageA (V @ "x"))) (Put "TEST")
    ]
  ]

scaling :: Benchmark
scaling = bgroup "Scaling"
  [ bgroup "2 divs"
    [ bench "normal" $ nf (renderByteString . divs2) "input"
    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs2 (V @ "x")) (Put "input")
    ]
  , bgroup "4 divs"
    [ bench "normal" $ nf (renderByteString . divs4) "input"
    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs4 (V @ "x")) (Put "input")
    ]
  , bgroup "8 divs"
    [ bench "normal" $ nf (renderByteString . divs8) "input"
    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs8 (V @ "x")) (Put "input")
    ]
  , bgroup "16 divs"
    [ bench "normal" $ nf (renderByteString . divs16) "input"
    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs16 (V @ "x")) (Put "input")
    ]
  , bgroup "32 divs"
    [ bench "normal" $ nf (renderByteString . divs32) "input"
    , bench "compact" $ nf (renderCompactByteString . compactHTML $ divs32 (V @ "x")) (Put "input")
    ]
  ]
  where
    divs2 x = div_ "lorem;" # x # div_ "ipsum<>"
    divs4 = divs2 . divs2
    divs8 = divs4 . divs4
    divs16 = divs8 . divs8
    divs32 = divs16 . divs16