{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Benchmark where
import Data.Array.IArray
import Data.Array.Unboxed (UArray)
import Data.List
import Data.Monoid
import Criterion
import Criterion.IO
import Criterion.Config
import Criterion.Main
import Criterion.Monad
import Criterion.Types
import Criterion.Environment
import Control.Monad
import Control.Monad.Trans (liftIO)
import Control.DeepSeq
import System.IO
import System.Directory
import System.Environment
instance (Ix dim, IArray UArray e) => NFData (UArray dim e) where
rnf a = a ! head (indices a) `seq` ()
-- Much like defaultMain, but we ignore any non-flag command line arguments,
-- which we take as the inputs to the program itself (returned via getArg')
--
runBenchmark :: [Benchmark] -> IO ()
runBenchmark = runBenchmarkWith defaultConfig (return ())
runBenchmarkWith :: Config -> Criterion () -> [Benchmark] -> IO ()
runBenchmarkWith defCfg prep bs = do
(cfg, _) <- parseArgs defCfg defaultOptions =<< getArgs
withConfig cfg $
if cfgPrintExit cfg == List
then do
_ <- note "Benchmarks:\n"
mapM_ (note " %s\n") (sort $ concatMap benchNames bs)
else do
case getLast $ cfgSummaryFile cfg of
Just fn -> liftIO $ writeFileOnce fn "Name,Mean,MeanLB,MeanUB,Stddev,StddevLB,StddevUB\n"
Nothing -> return ()
env <- measureEnvironment
let shouldRun = const True
prep
runAndAnalyse shouldRun env $ BenchGroup "" bs
writeFileOnce :: FilePath -> String -> IO ()
writeFileOnce fn line = do
exists <- doesFileExist fn
size <- withFile fn ReadWriteMode hFileSize
unless (exists && size > 0) $ writeFile fn line