{-# LANGUAGE DataKinds #-} 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 " ++ commas n ++ ": " ++ commas n' allocsError :: Int -> Int -> Weight -> Maybe String allocsError n i w | n' > (n+1) = Just $ "More" ++ answer | n' < (n-1) = Just $ "Less" ++ answer | otherwise = Nothing where n' = round (fromIntegral (weightAllocatedBytes w) / (10^i) :: Rational) :: Int answer = " allocated bytes than " ++ pretty (show n) ++ ": " ++ pretty (show n') pretty (a:as) = a : '.' : as ++ " e" ++ show (length as+i) pretty _ = "" f :: NFData b => String -> Int64 -> (a -> b) -> a -> Weigh () f s n g x = validateFunc s g x (allocs n) main :: IO () main = withSystemTempDirectory "compile" $ \tmp -> mainWith $ do -- nixpkgs: 1b27260 -- ghc: 8.4.1 f "()" 144 renderByteString () f "Int" 216 renderByteString (123456789 :: Int) f "Word" 216 renderByteString (123456789 :: Word) f "Char" 232 renderByteString 'a' f "Integer" 248 renderByteString (123456789 :: Integer) f "Proxy" 280 renderByteString (Proxy :: Proxy "a") f "oneElement Proxy" 280 (renderByteString . S.oneElement) (Proxy :: Proxy "b") f "oneElement ()" 280 (renderByteString . S.oneElement) () f "oneAttribute ()" 280 (renderByteString . A.class_) () f "oneAttribute Proxy" 280 (renderByteString . A.class_) (Proxy :: Proxy "c") f "listElement" 352 (renderByteString . S.listElement) () f "Double" 360 renderByteString (123456789 :: Double) f "oneElement" 368 (renderByteString . S.oneElement) "" f "nestedElement" 368 (renderByteString . S.nestedElement) "" f "listOfAttributes" 352 (\x -> renderByteString [A.class_ x, A.class_ x]) () f "Float" 400 renderByteString (123456789 :: Float) f "oneAttribute" 408 (renderByteString . A.class_) "" f "parallelElement" 520 (renderByteString . S.parallelElement) "" f "parallelAttribute" 584 (\x -> renderByteString $ A.class_ x # A.id_ x) "" f "elementWithAttribute" 584 (\x -> renderByteString $ div_A (A.class_ x) x) "" f "listOfListOf" 632 (\x -> renderByteString $ div_ [i_ [span_ x]]) () f "helloWorld" 1232 (renderByteString . M.helloWorld) () f "page" 1512 (renderByteString . M.page) () f "table" 1664 (renderByteString . M.table) (2,2) f "AttrShort" 2608 (renderByteString . M.attrShort) () f "pageA" 2960 (renderByteString . M.pageA) () f "AttrLong" 3352 (renderByteString . M.attrLong) () f "Big table" 19968 (renderByteString . M.table) (15,15) f "Big page" 25064 (renderByteString . B.page) () validateAction "Compile Library" (compile tmp) "Html" (allocsError 1021 6) validateAction "Compile Small.hs" (compile tmp) "Small" (allocsError 1061 6) validateAction "Compile Medium.hs" (compile tmp) "Medium" (allocsError 1790 6) validateAction "Compile Big.hs" (compile tmp) "Big" (allocsError 2470 6) validateAction "Compile Alloc.hs" (compile tmp) "bench/Alloc.hs" (allocsError 2531 6) validateAction "Compile Perf.hs" (compile tmp) "bench/Perf.hs" (allocsError 4809 6) 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