-- | Simple benchmarking of IO functions. module Cryptol.Utils.Benchmark ( BenchmarkStats (..) , benchmark , secs ) where import Criterion.Measurement (runBenchmark, secs, threshold) import Criterion.Measurement.Types import Data.Int import qualified Data.Vector as V import qualified Data.Vector.Unboxed as U -- | Statistics returned by 'benchmark'. -- -- This is extremely crude compared to the full analysis that criterion can do, -- but is enough for now. data BenchmarkStats = BenchmarkStats { benchAvgTime :: !Double , benchAvgCpuTime :: !Double , benchAvgCycles :: !Int64 } deriving Show -- | Benchmark the application of the given function to the given input and the -- execution of the resulting IO action to WHNF, spending at least the given -- amount of time in seconds to collect measurements. benchmark :: Double -> (a -> IO b) -> a -> IO BenchmarkStats benchmark period f x = do (meas, _) <- runBenchmark (whnfAppIO f x) period let meas' = rescale <$> V.filter ((>= threshold) . measTime) meas len = length meas' sumMeasure sel = U.sum $ measure sel meas' pure BenchmarkStats { benchAvgTime = sumMeasure measTime / fromIntegral len , benchAvgCpuTime = sumMeasure measCpuTime / fromIntegral len , benchAvgCycles = sumMeasure measCycles `div` fromIntegral len }