module Hyperion.Benchmark
(
Benchmark(..)
, bench
, bgroup
, env
, series
, Batch
, runBatch
, nf
, nfIO
, whnf
, whnfIO
, Env
, use
) where
import Control.Exception (evaluate)
import Control.Monad.State.Strict (modify')
import Data.Monoid
import Data.Vector (Vector)
import Data.Int (Int64)
import Data.Text (Text)
import qualified Data.Text as Text
import Control.DeepSeq
import Hyperion.Internal
data Benchmark where
Bench :: Text -> Batch () -> Benchmark
Group :: Text -> [Benchmark] -> Benchmark
Bracket :: NFData r => IO r -> (r -> IO ()) -> (Env r -> Benchmark) -> Benchmark
Series :: (Show a, Enum a) => Vector a -> (a -> Benchmark) -> Benchmark
sp :: ShowS
sp = showChar ' '
instance Show Benchmark where
showsPrec _ (Bench name _) =
showString "Bench" . sp . shows name . sp . showString "_"
showsPrec x (Group name bks) =
showString "Group" . sp . shows name . sp . showsPrec x bks
showsPrec x (Bracket _ _ f) =
showString "Bracket" . sp . showString "(\\_ -> " . showsPrec x (f Empty) . showString ")"
showsPrec x (Series xs f) =
showString "Series" . sp . shows xs . sp . showsPrec x (f <$> xs)
bench :: String -> Batch () -> Benchmark
bench name batch = Bench (Text.pack name) batch
bgroup :: String -> [Benchmark] -> Benchmark
bgroup name bks = Group (Text.pack name) bks
series :: (Show a, Enum a) => Vector a -> (a -> Benchmark) -> Benchmark
series = Series
env
:: NFData r
=> IO r
-> (r -> IO ())
-> (Env r -> Benchmark)
-> Benchmark
env = Bracket
whnf :: (a -> b) -> a -> Batch ()
whnf f x = Batch $ modify' (<> pureFunc id f x)
nf :: NFData b => (a -> b) -> a -> Batch ()
nf f x = Batch $ modify' (<> pureFunc rnf f x)
pureFunc :: (b -> c) -> (a -> b) -> a -> Int64 -> IO ()
pureFunc reduce f0 x0 = go f0 x0
where go f x n
| n <= 0 = return ()
| otherwise = evaluate (reduce (f x)) >> go f x (n1)
nfIO :: NFData a => IO a -> Batch ()
nfIO m = Batch $ modify' (<> impure rnf m)
whnfIO :: IO a -> Batch ()
whnfIO m = Batch $ modify' (<> impure id m)
impure :: (a -> b) -> IO a -> Int64 -> IO ()
impure strategy a = go
where go n
| n <= 0 = return ()
| otherwise = a >>= (evaluate . strategy) >> go (n1)