packages feed

type-of-html-1.4.0.2: bench/Alloc.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE CPP       #-}

-- | Note that the allocation numbers are only reproducible on linux using the nix shell.

module Main where

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

import Weigh
import Control.DeepSeq
import Data.Proxy
import Data.Int

import System.IO.Temp
import GHC
import GHC.Paths (libdir)
import DynFlags
import Control.Monad

allocs :: Int64 -> Weight -> Maybe String
allocs n w
  | n' > n = Just $ "More" ++ answer
  | n' < n = Just $ "Less" ++ answer
  | otherwise = Nothing
  where n' = weightAllocatedBytes w
        answer = " allocated bytes than expected: " ++ show (abs $ n' - n)

allocsError :: Int -> Int -> Int -> Weight -> Maybe String
allocsError i m n w
  | n' > (m'+1) = Just $ "More" ++ answer
  | n' < (m'-1) = Just $ "Less" ++ answer
  | otherwise = Nothing
  where n' = round (fromIntegral (weightAllocatedBytes w) / (10^i) :: Rational) :: Int
        m' = n + m
        answer = " allocated bytes than expected: " ++ pretty (abs $ m' - n')
        pretty x = show x ++ " e" ++ show i

f :: NFData b => String -> (a -> b) -> a -> Int64 -> Weigh ()
f s g x n = validateFunc s g x (allocs n)

main :: IO ()
main = withSystemTempDirectory "compile" $ \tmp -> mainWith $ do

  --                                                                        ghc version    822   843   861
  f "()"                   renderByteString ()                                    $ ghc [   96             ]
  f "Int"                  renderByteString (123456789 :: Int)                    $ ghc [  216             ]
  f "Word"                 renderByteString (123456789 :: Word)                   $ ghc [  216             ]
  f "Char"                 renderByteString 'a'                                   $ ghc [  232             ]
  f "Integer"              renderByteString (123456789 :: Integer)                $ ghc [  248             ]
  f "Proxy"                renderByteString (Proxy :: Proxy "a")                  $ ghc [  280             ]
  f "oneElement Proxy"     (renderByteString . S.oneElement) (Proxy :: Proxy "b") $ ghc [  280             ]
  f "oneElement ()"        (renderByteString . S.oneElement) ()                   $ ghc [  280             ]
  f "oneAttribute ()"      (renderByteString . A.class_) ()                       $ ghc [  280             ]
  f "oneAttribute Proxy"   (renderByteString . A.class_) (Proxy :: Proxy "c")     $ ghc [  280             ]
  f "listElement"          (renderByteString . S.listElement) ()                  $ ghc [  392             ]
  f "Double"               renderByteString (123456789 :: Double)                 $ ghc [  360             ]
  f "oneElement"           (renderByteString . S.oneElement) ""                   $ ghc [  368             ]
  f "nestedElement"        (renderByteString . S.nestedElement) ""                $ ghc [  368             ]
  f "listOfAttributes"     (\x -> renderByteString [A.class_ x, A.class_ x]) ()   $ ghc [  488,    0,  -16 ]
  f "Float"                renderByteString (123456789 :: Float)                  $ ghc [  400             ]
  f "oneAttribute"         (renderByteString . A.class_) ""                       $ ghc [  408             ]
  f "parallelElement"      (renderByteString . S.parallelElement) ""              $ ghc [  520             ]
  f "parallelAttribute"    (\x -> renderByteString $ A.class_ x # A.id_ x) ""     $ ghc [  584             ]
  f "elementWithAttribute" (\x -> renderByteString $ div_A (A.class_ x) x) ""     $ ghc [  584             ]
  f "listOfListOf"         (\x -> renderByteString $ div_ [i_ [span_ x]]) ()      $ ghc [  896,   88,   -8 ]
  f "helloWorld"           (renderByteString . M.helloWorld) ()                   $ ghc [ 1248,    0,   16 ]
  f "page"                 (renderByteString . M.page) ()                         $ ghc [ 1256             ]
  f "table"                (renderByteString . M.table) (2,2)                     $ ghc [ 1920, -256,   -8 ]
  f "AttrShort"            (renderByteString . M.attrShort) ()                    $ ghc [ 3184,   48       ]
  f "pageA"                (renderByteString . M.pageA) ()                        $ ghc [ 2536, -216       ]
  f "AttrLong"             (renderByteString . M.attrLong) ()                     $ ghc [ 3184,   48, -192 ]
  f "Big table"            (renderByteString . M.table) (15,15)                   $ ghc [12904, 7064,   -8 ]
  f "Big page"             (renderByteString . B.page) ()                         $ ghc [25208, -248,  -40 ]
  let g x y z = validateAction x (compile tmp) y . allocsError 7 z                $ ghc [  104,    0,    2 ]
  g "Compile Library"   "Html"                                                    $ ghc [    0             ]
  g "Compile Small.hs"  "Small"                                                   $ ghc [    0             ]
  g "Compile Medium.hs" "Medium"                                                  $ ghc [   37,    0,    2 ]
  g "Compile Big.hs"    "Big"                                                     $ ghc [   70,    0,    3 ]
  g "Compile Alloc.hs"  "bench/Alloc.hs"                                          $ ghc [   74,    2       ]
  g "Compile Perf.hs"   "bench/Perf.hs"                                           $ ghc [  179,    2       ]
  g "Compile X0.hs"     "bench/Compilation/X0.hs"                                 $ ghc [    4,   -2       ]
  g "Compile X1.hs"     "bench/Compilation/X1.hs"                                 $ ghc [    3             ]
  g "Compile X2.hs"     "bench/Compilation/X2.hs"                                 $ ghc [    5             ]
  g "Compile X4.hs"     "bench/Compilation/X4.hs"                                 $ ghc [    7             ]
  g "Compile X8.hs"     "bench/Compilation/X8.hs"                                 $ ghc [   12             ]
  g "Compile X16.hs"    "bench/Compilation/X16.hs"                                $ ghc [   23             ]
  g "Compile X32.hs"    "bench/Compilation/X32.hs"                                $ ghc [   64,    0       ]
  g "Compile X64.hs"    "bench/Compilation/X64.hs"                                $ ghc [  203,    2,   -3 ]
  g "Compile X128.hs"   "bench/Compilation/X128.hs"                               $ ghc [  711,    4,   -5 ]

ghc :: Num a => [a] -> a
ghc [] = 0
ghc (x:xs) = sum $ x:[y | (y, v) <- zip xs supportedGhcs, v < __GLASGOW_HASKELL__]

  where supportedGhcs = [802, 804] :: [Int]


compile :: String -> String -> IO ()
compile out m =
  void . defaultErrorHandler defaultFatalMessager defaultFlushOut . runGhc (Just libdir) $ do
    dflags <- getSessionDynFlags
    void $ setSessionDynFlags (dflags {optLevel = 2, importPaths = ["src", "bench"], hiDir = Just out, objectDir = Just out, outputFile = Just (out ++ "/out")})
    target <- guessTarget m Nothing
    setTargets [target]
    load LoadAllTargets