serialise-0.1.0.0: bench/micro/Micro.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
module Micro
( benchmarks -- :: [Benchmark]
) where
import Criterion.Main
import Control.DeepSeq
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BS
import Foreign
import Codec.CBOR.Magic
import qualified Micro.MemSize
import Micro.DeepSeq ()
import qualified Micro.Load as Micro.Load
import qualified Micro.Types as Micro.Types ()
import qualified Micro.ReadShow as Micro.ReadShow
import qualified Micro.PkgBinary as Micro.PkgBinary
import qualified Micro.PkgCereal as Micro.PkgCereal
import qualified Micro.PkgStore as Micro.PkgStore
import qualified Micro.PkgAesonGeneric as Micro.PkgAesonGeneric
import qualified Micro.PkgAesonTH as Micro.PkgAesonTH
import qualified Micro.CBOR as Micro.CBOR
--------------------------------------------------------------------------------
-- A simple driver, for running every set of benchmarks.
benchmarks :: [Benchmark]
benchmarks =
[ bgroup "reference"
[ bench "deepseq" (whnf rnf tstdata)
, bench "memSize" (whnf (flip Micro.MemSize.memSize 0) tstdata)
]
, bgroup "encoding" $ deepseq tstdata
[ bench "binary" (whnf perfEncodeBinary tstdata)
, bench "cereal" (whnf perfEncodeCereal tstdata)
, bench "aeson generic" (whnf perfEncodeAesonGeneric tstdata)
, bench "aeson TH" (whnf perfEncodeAesonTH tstdata)
, bench "read/show" (whnf perfEncodeReadShow tstdata)
, bench "store" (whnf perfEncodeStore tstdata)
, bench "cbor" (whnf perfEncodeCBOR tstdata)
]
, bgroup "decoding" $ deepseq (tstdataB, tstdataC, tstdataA, tstdataS,
tstdataR)
[ bench "binary" (whnf perfDecodeBinary tstdataB)
, bench "cereal" (whnf perfDecodeCereal tstdataC)
, bench "aeson generic" (whnf perfDecodeAesonGeneric tstdataA)
, bench "aeson TH" (whnf perfDecodeAesonTH tstdataA)
, bench "read/show" (whnf perfDecodeReadShow tstdataS)
, bench "store" (whnf perfDecodeStore tstdataP)
, bench "cbor" (whnf perfDecodeCBOR tstdataR)
]
, bgroup "decoding + deepseq" $ deepseq (tstdataB, tstdataC, tstdataA,
tstdataS, tstdataR)
[ bench "binary" (nf perfDecodeBinary tstdataB)
, bench "cereal" (nf perfDecodeCereal tstdataC)
, bench "aeson generic" (nf perfDecodeAesonGeneric tstdataA)
, bench "aeson TH" (nf perfDecodeAesonTH tstdataA)
, bench "read/show" (nf perfDecodeReadShow tstdataS)
, bench "store" (nf perfDecodeStore tstdataP)
, bench "cbor" (nf perfDecodeCBOR tstdataR)
]
, env lowlevelPtrEnv $ \ptr ->
bgroup "lowlevel"
[ bench "grabWord16" (nf grabWord16 ptr)
, bench "grabWord32" (nf grabWord32 ptr)
, bench "grabWord64" (nf grabWord64 ptr)
]
]
where
-- Input data
tstdata = Micro.Load.mkBigTree 16 -- tree of size 2^16
!tstdataB = combineChunks $ Micro.PkgBinary.serialise tstdata
!tstdataC = combineChunks $ Micro.PkgCereal.serialise tstdata
!tstdataA = combineChunks $ Micro.PkgAesonTH.serialise tstdata
!tstdataS = combineChunks $ Micro.ReadShow.serialise tstdata
!tstdataP = Micro.PkgStore.serialise tstdata
!tstdataR = combineChunks $ Micro.CBOR.serialise tstdata
-- Encoding tests
perfEncodeBinary = BS.length . Micro.PkgBinary.serialise
perfEncodeCereal = BS.length . Micro.PkgCereal.serialise
perfEncodeAesonGeneric = BS.length . Micro.PkgAesonGeneric.serialise
perfEncodeAesonTH = BS.length . Micro.PkgAesonTH.serialise
perfEncodeReadShow = BS.length . Micro.ReadShow.serialise
perfEncodeStore = B.length . Micro.PkgStore.serialise
perfEncodeCBOR = BS.length . Micro.CBOR.serialise
-- Decoding tests
perfDecodeBinary = Micro.PkgBinary.deserialise
perfDecodeCereal = Micro.PkgCereal.deserialise
perfDecodeAesonGeneric = Micro.PkgAesonGeneric.deserialise
perfDecodeAesonTH = Micro.PkgAesonTH.deserialise
perfDecodeReadShow = Micro.ReadShow.deserialise
perfDecodeStore = Micro.PkgStore.deserialise
perfDecodeCBOR = Micro.CBOR.deserialise
-- | Allocate an 8-byte pointer, write a 64-bit word into
-- it, and return a @'Ptr' ()@ to be used by the low-level routines.
lowlevelPtrEnv :: IO (Ptr ())
lowlevelPtrEnv = do
ptr <- mallocBytes 8
poke ptr (0xDEADBEEFCAFEBABE :: Word64)
return (castPtr ptr)
-- Create lazy bytestring that contains single chunk, from the
-- bytestring that may contain multiple chunks.
combineChunks :: BS.ByteString -> BS.ByteString
combineChunks = BS.fromStrict . BS.toStrict
--------------------------------------------------------------------------------
-- An NFData instance for Ptr is in deepseq HEAD/1.4.2, but it's not released.
#if !MIN_VERSION_deepseq(1,4,2)
instance NFData (Ptr a) where rnf !_ = ()
#endif