packages feed

large-hashable-0.1.1.0: benchmark/Data/LargeHashable/Benchmarks/Main.hs

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Data.LargeHashable.Benchmarks.Main (main) where

import Control.DeepSeq
import Criterion
import Criterion.Main
import Data.SafeCopy
import Data.Serialize.Put
import GHC.Generics
import qualified Data.Bytes.Serial as S
import qualified Data.LargeHashable as LH
import qualified Data.LargeHashable.Class as LH
import qualified Data.LargeHashable.Intern as LH
import qualified Data.LargeHashable.Benchmarks.CryptoHash as CH
import qualified Data.LargeHashable.Benchmarks.Serial as Serial
import qualified Data.LargeHashable.Benchmarks.Text as TextBench
import qualified Data.Text as T

data Patient
    = Patient
    { p_firstName :: !T.Text
    , p_lastName :: !T.Text
    , p_note :: !T.Text
    , p_age :: !Int
    }
    deriving (Eq, Show, NFData, Generic)

$(deriveSafeCopy 0 'base ''Patient)
$(LH.deriveLargeHashable ''Patient)

instance S.Serial Patient

instance CH.LargeHashable Patient where
    hashUpdate ctx0 p =
        let !ctx1 = CH.hashUpdate ctx0 (p_firstName p)
            !ctx2 = CH.hashUpdate ctx1 (p_lastName p)
            !ctx3 = CH.hashUpdate ctx2 (p_note p)
            !ctx4 = CH.hashUpdate ctx3 (p_age p)
        in ctx4

updateHashPatient :: Patient -> LH.LH ()
updateHashPatient p =
    {-# SCC "updateHash/LargHashable" #-}
    do {-# SCC "updateHash/firstName" #-} LH.updateHash (p_firstName p)
       {-# SCC "updateHash/lastName" #-} LH.updateHash (p_lastName p)
       {-# SCC "updateHash/note" #-} LH.updateHash (p_note p)
       {-# SCC "updateHash/age" #-} LH.updateHash (p_age p)

mkPatList :: Int -> [Patient]
mkPatList n =
    let l = map mkPat [1..n]
    in l `deepseq` l
    where
      mkPat i =
          Patient
          { p_firstName = "Stefan"
          , p_lastName = "Wehr"
          , p_note = "Dies ist ein bißchen mehr Text, aber auch nicht richtig lang"
          , p_age = i
          }

_NUM_ :: Int
_NUM_ = 100000

patList :: [Patient]
patList = mkPatList _NUM_

main :: IO ()
main =
    defaultMain
    [ env (return patList) $ \l ->
        bgroup "patList"
        [ bench "safecopy" $ whnf (CH.hashMd5 . runPut . safePut) l
        , bench "cryptohash" $ whnf CH.hashMd5 l
        , bench "large-hashable (Manual)" $ whnf (LH.runLH LH.md5HashAlgorithm . LH.updateHashList updateHashPatient) l
        , bench "large-hashable (TH)" $ whnf (LH.largeHash LH.md5HashAlgorithm) l
        , bench "large-hashable (Generic)" $ whnf (LH.runLH LH.md5HashAlgorithm . LH.genericUpdateHash) l
        , bench "large-hashable-serial (TH)" $ whnf (Serial.serialLargeHash LH.md5HashAlgorithm) l
        ]
    , env TextBench.setup $ \ ~(text, string) ->
        bgroup "text"
        [ bench "text-utf8" $ whnf TextBench.benchTextUtf8 text
        , bench "text-utf16" $ whnf TextBench.benchTextUtf16 text
        , bench "text-unicode" $ whnf TextBench.benchTextUnicode text
        , bench "string" $ whnf TextBench.benchTextString string
        ]
    ]