packages feed

beamable-0.1.1.0: bench/Bench.hs

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RankNTypes #-}
module Main where

import Criterion
import Criterion.Main
import Control.DeepSeq
import Data.Beamable
import Data.List (sort)
import Data.Word
import GHC.Generics

main :: IO ()
main = defaultMain
    [ bgroup "roundTrip" $ allBenches roundTrip
    , bgroup "encode" $ allBenches encodeF
    ]
  where
    !_unused  = sum testWords
    !_unused' = sum testInts

-- TODO: generalize this such that we can easily benchmark decoding
-- by itself.  At present we can only benchmark decoding by looking at
-- the round-trip times.
allBenches :: (forall a. (Beamable a) => a -> a) -> [Benchmark]
allBenches f =
    [ bgroup "Int"  $ map (mkBenchGroup f) testInts
    , bgroup "Word" $ map (mkBenchGroup f) testWords
    , bench "[Int]" $ nf f testInts
    , bench "[Int]1000" $ nf f longList
    , bench "(Word,Word)" $ nf f ((0,1000000) :: (Word,Word))
    , bench "(Int,Int,(Word,Int))" $ nf f ((0,23451345,(1000000,-4213)) :: (Int,Int,(Word,Int)))
    , bench "TestG1" $ nf f (TestG1 10 20 :: TestG [Int])
    , bench "TestG2" $ nf f (TestG2 [1..5] 20 :: TestG [Int])
    ]
  where
    longList = replicate 1000 (1::Int)
    !_unused = sum longList

mkBenchGroup f x = bench (show x) $ whnf f x

roundTrip x = decode (encode x) `asTypeOf` x

-- we use the slightly odd type because it fits into 'allBenches'
-- easily.  encode produces a strict ByteString, so we can just force
-- it to WHNF to benchmark it.
encodeF :: Beamable a => a -> a
encodeF x = encode x `seq` x

test10s :: [Word]
test10s = [10^x | x <- [0,2..10]]
testWords = 0: (sort $ test10s ++ map (*5) test10s)

testInts :: [Int]
testInts = let xs = map fromIntegral testWords
           in reverse (map negate xs) ++ tail xs 

data TestG a = TestG1 Int Int | TestG2 a Word
    deriving (Eq, Show, Generic)

instance Beamable a => Beamable (TestG a)

instance NFData a => NFData (TestG a) where
    rnf (TestG1 a b) = a `seq` b `seq` ()
    rnf (TestG2 a b) = a `deepseq` b `seq` ()