{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeFamilies #-}
module InitTails (initTailsBenchmarks) where
#if MIN_VERSION_gauge(0,2,0)
import Gauge
#else
import Gauge.Main
#endif
import Data.Sequences as Ss
import Data.MonoTraversable
import Type.Reflection (Typeable, typeRep)
import Control.DeepSeq
import Data.Foldable (foldl')
import Data.Functor ((<&>))
import Data.ByteString (StrictByteString)
import Data.ByteString.Lazy (LazyByteString)
import qualified Data.Text as TS
import qualified Data.Text.Lazy as TL
import Data.Sequence (Seq)
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Storable as VS
initTailsBenchmarks :: Benchmark
initTailsBenchmarks = bgroup "InitTails"
[ bmg @[Char]
, bmg @StrictByteString
, bmg @LazyByteString
, bmg @TS.Text
, bmg @TL.Text
, bmg @(Seq Char)
, bmg @(V.Vector Char)
, bmg @(VU.Vector Char)
, bmg @(VS.Vector Char)
]
bmg :: forall seq.
( TestLabel seq
, NFData seq
, IsSequence seq
, Num (Index seq)
, Enum (Element seq)
) => Benchmark
bmg = bgroup (testLabel @seq) $ bm <$> labelledLengths
where
bm :: (String,[Int]) -> Benchmark
bm (label,lengths) = bgroup label $
[ ("weak", weakConsume)
, ("deep", deepConsume)
] <&> \(wdLabel,consume) -> bench wdLabel
$ nf (map $ consume . initTails @seq)
$ (`Ss.replicate` (toEnum 65)) . fromIntegral <$> lengths
labelledLengths =
[ ("tiny", [0,1,2,5,10])
, ("small", [100,150,200,300])
, ("medium", [1000,1500,2000,2500])
, ("large", [10000,20000,50000])
]
class Typeable a => TestLabel a where
testLabel :: String
testLabel = show $ typeRep @a
instance TestLabel [Char]
instance TestLabel StrictByteString where testLabel = "StrictByteString"
instance TestLabel LazyByteString where testLabel = "LazyByteString"
instance TestLabel TS.Text where testLabel = "StrictText"
instance TestLabel TL.Text where testLabel = "LazyText"
instance TestLabel (Seq Char) where testLabel = "Seq"
instance TestLabel (V.Vector Char) where testLabel = "Vector"
instance TestLabel (VU.Vector Char) where testLabel = "UnboxedVector"
instance TestLabel (VS.Vector Char) where testLabel = "StorableVector"
-- *Consume used to keep memory usage lower
deepConsume :: NFData seq => [(seq,seq)] -> ()
deepConsume = foldl' (\() (is,ts) -> deepseq is $ deepseq ts ()) ()
weakConsume :: [(seq,seq)] -> ()
weakConsume = foldl' (\() (_,_) -> ()) ()