{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Test.Tasty.Bench
(
#ifdef MIN_VERSION_tasty
defaultMain
, Benchmark
, bench
, bgroup
, bcompare
, bcompareWithin
, env
, envWithCleanup
,
#endif
Benchmarkable(..)
, nf
, whnf
, nfIO
, whnfIO
, nfAppIO
, whnfAppIO
, measureCpuTime
, measureCpuTimeAndStDev
#ifdef MIN_VERSION_tasty
, benchIngredients
, consoleBenchReporter
, csvReporter
, svgReporter
, RelStDev(..)
, FailIfSlower(..)
, FailIfFaster(..)
, CsvPath(..)
, BaselinePath(..)
, SvgPath(..)
, TimeMode(..)
, locateBenchmark
, mapLeafBenchmarks
#else
, Timeout(..)
, RelStDev(..)
#endif
) where
import Prelude hiding (Int, Integer)
import qualified Prelude
import Control.Applicative
import Control.Arrow (first, second)
import Control.DeepSeq (NFData, force, rnf)
import Control.Exception (bracket, bracket_, evaluate)
import Control.Monad (void, unless, guard, (>=>), when)
import Data.Foldable (foldMap, traverse_)
import Data.Int (Int64)
import Data.IORef
import Data.List (intercalate, stripPrefix, isPrefixOf, genericLength, genericDrop, foldl1')
import Data.Maybe (fromMaybe)
import Data.Monoid (All(..), Any(..))
import Data.Proxy
import Data.Traversable (forM)
import Data.Word (Word64)
import GHC.Conc
import GHC.IO.Encoding
import GHC.Stats
import GHC.Types (SPEC(..))
import System.CPUTime
import System.Exit
import System.IO
import System.IO.Unsafe
import System.Mem
import Text.Printf
#ifdef MIN_VERSION_tasty
import Data.Semigroup (Semigroup(..))
import qualified Data.IntMap.Strict as IM
import Data.IntMap (IntMap)
import Data.Sequence (Seq, (<|))
import qualified Data.Sequence as Seq
import qualified Data.Set as S
import Test.Tasty hiding (defaultMain)
import qualified Test.Tasty
import Test.Tasty.Ingredients
import Test.Tasty.Ingredients.ConsoleReporter
import Test.Tasty.Options
import Test.Tasty.Patterns.Eval (eval, asB, withFields)
import Test.Tasty.Patterns.Types (Expr (And, Field, IntLit, NF, StringLit, Sub))
import qualified Test.Tasty.Patterns.Types as Patterns
import Test.Tasty.Providers
import Test.Tasty.Runners
#endif
#if MIN_VERSION_base(4,11,0)
import GHC.Clock (getMonotonicTime)
#else
import Data.Time.Clock.POSIX (getPOSIXTime)
#endif
#if defined(mingw32_HOST_OS)
import Data.Word (Word32)
#endif
#ifndef MIN_VERSION_tasty
data Timeout
= Timeout
Prelude.Integer
String
| NoTimeout
deriving (Show)
type Progress = ()
#endif
newtype RelStDev = RelStDev Double
deriving
( RelStDev -> RelStDev -> Bool
(RelStDev -> RelStDev -> Bool)
-> (RelStDev -> RelStDev -> Bool) -> Eq RelStDev
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RelStDev -> RelStDev -> Bool
== :: RelStDev -> RelStDev -> Bool
$c/= :: RelStDev -> RelStDev -> Bool
/= :: RelStDev -> RelStDev -> Bool
Eq
, Eq RelStDev
Eq RelStDev =>
(RelStDev -> RelStDev -> Ordering)
-> (RelStDev -> RelStDev -> Bool)
-> (RelStDev -> RelStDev -> Bool)
-> (RelStDev -> RelStDev -> Bool)
-> (RelStDev -> RelStDev -> Bool)
-> (RelStDev -> RelStDev -> RelStDev)
-> (RelStDev -> RelStDev -> RelStDev)
-> Ord RelStDev
RelStDev -> RelStDev -> Bool
RelStDev -> RelStDev -> Ordering
RelStDev -> RelStDev -> RelStDev
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RelStDev -> RelStDev -> Ordering
compare :: RelStDev -> RelStDev -> Ordering
$c< :: RelStDev -> RelStDev -> Bool
< :: RelStDev -> RelStDev -> Bool
$c<= :: RelStDev -> RelStDev -> Bool
<= :: RelStDev -> RelStDev -> Bool
$c> :: RelStDev -> RelStDev -> Bool
> :: RelStDev -> RelStDev -> Bool
$c>= :: RelStDev -> RelStDev -> Bool
>= :: RelStDev -> RelStDev -> Bool
$cmax :: RelStDev -> RelStDev -> RelStDev
max :: RelStDev -> RelStDev -> RelStDev
$cmin :: RelStDev -> RelStDev -> RelStDev
min :: RelStDev -> RelStDev -> RelStDev
Ord
, Key -> RelStDev -> ShowS
[RelStDev] -> ShowS
RelStDev -> String
(Key -> RelStDev -> ShowS)
-> (RelStDev -> String) -> ([RelStDev] -> ShowS) -> Show RelStDev
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Key -> RelStDev -> ShowS
showsPrec :: Key -> RelStDev -> ShowS
$cshow :: RelStDev -> String
show :: RelStDev -> String
$cshowList :: [RelStDev] -> ShowS
showList :: [RelStDev] -> ShowS
Show
, ReadPrec [RelStDev]
ReadPrec RelStDev
Key -> ReadS RelStDev
ReadS [RelStDev]
(Key -> ReadS RelStDev)
-> ReadS [RelStDev]
-> ReadPrec RelStDev
-> ReadPrec [RelStDev]
-> Read RelStDev
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Key -> ReadS RelStDev
readsPrec :: Key -> ReadS RelStDev
$creadList :: ReadS [RelStDev]
readList :: ReadS [RelStDev]
$creadPrec :: ReadPrec RelStDev
readPrec :: ReadPrec RelStDev
$creadListPrec :: ReadPrec [RelStDev]
readListPrec :: ReadPrec [RelStDev]
Read
, Integer -> RelStDev
RelStDev -> RelStDev
RelStDev -> RelStDev -> RelStDev
(RelStDev -> RelStDev -> RelStDev)
-> (RelStDev -> RelStDev -> RelStDev)
-> (RelStDev -> RelStDev -> RelStDev)
-> (RelStDev -> RelStDev)
-> (RelStDev -> RelStDev)
-> (RelStDev -> RelStDev)
-> (Integer -> RelStDev)
-> Num RelStDev
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: RelStDev -> RelStDev -> RelStDev
+ :: RelStDev -> RelStDev -> RelStDev
$c- :: RelStDev -> RelStDev -> RelStDev
- :: RelStDev -> RelStDev -> RelStDev
$c* :: RelStDev -> RelStDev -> RelStDev
* :: RelStDev -> RelStDev -> RelStDev
$cnegate :: RelStDev -> RelStDev
negate :: RelStDev -> RelStDev
$cabs :: RelStDev -> RelStDev
abs :: RelStDev -> RelStDev
$csignum :: RelStDev -> RelStDev
signum :: RelStDev -> RelStDev
$cfromInteger :: Integer -> RelStDev
fromInteger :: Integer -> RelStDev
Num
, Num RelStDev
Num RelStDev =>
(RelStDev -> RelStDev -> RelStDev)
-> (RelStDev -> RelStDev)
-> (Rational -> RelStDev)
-> Fractional RelStDev
Rational -> RelStDev
RelStDev -> RelStDev
RelStDev -> RelStDev -> RelStDev
forall a.
Num a =>
(a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
$c/ :: RelStDev -> RelStDev -> RelStDev
/ :: RelStDev -> RelStDev -> RelStDev
$crecip :: RelStDev -> RelStDev
recip :: RelStDev -> RelStDev
$cfromRational :: Rational -> RelStDev
fromRational :: Rational -> RelStDev
Fractional
)
data TimeMode = CpuTime
| WallTime
#ifdef MIN_VERSION_tasty
instance IsOption RelStDev where
defaultValue :: RelStDev
defaultValue = Double -> RelStDev
RelStDev Double
0.05
parseValue :: String -> Maybe RelStDev
parseValue = (Double -> RelStDev) -> Maybe Double -> Maybe RelStDev
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> RelStDev
RelStDev (Maybe Double -> Maybe RelStDev)
-> (String -> Maybe Double) -> String -> Maybe RelStDev
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe Double
parsePositivePercents
optionName :: Tagged RelStDev String
optionName = String -> Tagged RelStDev String
forall a. a -> Tagged RelStDev a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"stdev"
optionHelp :: Tagged RelStDev String
optionHelp = String -> Tagged RelStDev String
forall a. a -> Tagged RelStDev a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"Target relative standard deviation of measurements in percents (5 by default). Large values correspond to fast and loose benchmarks, and small ones to long and precise. If it takes far too long, consider setting --timeout, which will interrupt benchmarks, potentially before reaching the target deviation."
newtype FailIfSlower = FailIfSlower Double
deriving
( FailIfSlower -> FailIfSlower -> Bool
(FailIfSlower -> FailIfSlower -> Bool)
-> (FailIfSlower -> FailIfSlower -> Bool) -> Eq FailIfSlower
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FailIfSlower -> FailIfSlower -> Bool
== :: FailIfSlower -> FailIfSlower -> Bool
$c/= :: FailIfSlower -> FailIfSlower -> Bool
/= :: FailIfSlower -> FailIfSlower -> Bool
Eq
, Eq FailIfSlower
Eq FailIfSlower =>
(FailIfSlower -> FailIfSlower -> Ordering)
-> (FailIfSlower -> FailIfSlower -> Bool)
-> (FailIfSlower -> FailIfSlower -> Bool)
-> (FailIfSlower -> FailIfSlower -> Bool)
-> (FailIfSlower -> FailIfSlower -> Bool)
-> (FailIfSlower -> FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower -> FailIfSlower)
-> Ord FailIfSlower
FailIfSlower -> FailIfSlower -> Bool
FailIfSlower -> FailIfSlower -> Ordering
FailIfSlower -> FailIfSlower -> FailIfSlower
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: FailIfSlower -> FailIfSlower -> Ordering
compare :: FailIfSlower -> FailIfSlower -> Ordering
$c< :: FailIfSlower -> FailIfSlower -> Bool
< :: FailIfSlower -> FailIfSlower -> Bool
$c<= :: FailIfSlower -> FailIfSlower -> Bool
<= :: FailIfSlower -> FailIfSlower -> Bool
$c> :: FailIfSlower -> FailIfSlower -> Bool
> :: FailIfSlower -> FailIfSlower -> Bool
$c>= :: FailIfSlower -> FailIfSlower -> Bool
>= :: FailIfSlower -> FailIfSlower -> Bool
$cmax :: FailIfSlower -> FailIfSlower -> FailIfSlower
max :: FailIfSlower -> FailIfSlower -> FailIfSlower
$cmin :: FailIfSlower -> FailIfSlower -> FailIfSlower
min :: FailIfSlower -> FailIfSlower -> FailIfSlower
Ord
, Key -> FailIfSlower -> ShowS
[FailIfSlower] -> ShowS
FailIfSlower -> String
(Key -> FailIfSlower -> ShowS)
-> (FailIfSlower -> String)
-> ([FailIfSlower] -> ShowS)
-> Show FailIfSlower
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Key -> FailIfSlower -> ShowS
showsPrec :: Key -> FailIfSlower -> ShowS
$cshow :: FailIfSlower -> String
show :: FailIfSlower -> String
$cshowList :: [FailIfSlower] -> ShowS
showList :: [FailIfSlower] -> ShowS
Show
, ReadPrec [FailIfSlower]
ReadPrec FailIfSlower
Key -> ReadS FailIfSlower
ReadS [FailIfSlower]
(Key -> ReadS FailIfSlower)
-> ReadS [FailIfSlower]
-> ReadPrec FailIfSlower
-> ReadPrec [FailIfSlower]
-> Read FailIfSlower
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Key -> ReadS FailIfSlower
readsPrec :: Key -> ReadS FailIfSlower
$creadList :: ReadS [FailIfSlower]
readList :: ReadS [FailIfSlower]
$creadPrec :: ReadPrec FailIfSlower
readPrec :: ReadPrec FailIfSlower
$creadListPrec :: ReadPrec [FailIfSlower]
readListPrec :: ReadPrec [FailIfSlower]
Read
, Integer -> FailIfSlower
FailIfSlower -> FailIfSlower
FailIfSlower -> FailIfSlower -> FailIfSlower
(FailIfSlower -> FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower)
-> (Integer -> FailIfSlower)
-> Num FailIfSlower
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: FailIfSlower -> FailIfSlower -> FailIfSlower
+ :: FailIfSlower -> FailIfSlower -> FailIfSlower
$c- :: FailIfSlower -> FailIfSlower -> FailIfSlower
- :: FailIfSlower -> FailIfSlower -> FailIfSlower
$c* :: FailIfSlower -> FailIfSlower -> FailIfSlower
* :: FailIfSlower -> FailIfSlower -> FailIfSlower
$cnegate :: FailIfSlower -> FailIfSlower
negate :: FailIfSlower -> FailIfSlower
$cabs :: FailIfSlower -> FailIfSlower
abs :: FailIfSlower -> FailIfSlower
$csignum :: FailIfSlower -> FailIfSlower
signum :: FailIfSlower -> FailIfSlower
$cfromInteger :: Integer -> FailIfSlower
fromInteger :: Integer -> FailIfSlower
Num
, Num FailIfSlower
Num FailIfSlower =>
(FailIfSlower -> FailIfSlower -> FailIfSlower)
-> (FailIfSlower -> FailIfSlower)
-> (Rational -> FailIfSlower)
-> Fractional FailIfSlower
Rational -> FailIfSlower
FailIfSlower -> FailIfSlower
FailIfSlower -> FailIfSlower -> FailIfSlower
forall a.
Num a =>
(a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
$c/ :: FailIfSlower -> FailIfSlower -> FailIfSlower
/ :: FailIfSlower -> FailIfSlower -> FailIfSlower
$crecip :: FailIfSlower -> FailIfSlower
recip :: FailIfSlower -> FailIfSlower
$cfromRational :: Rational -> FailIfSlower
fromRational :: Rational -> FailIfSlower
Fractional
)
instance IsOption FailIfSlower where
defaultValue :: FailIfSlower
defaultValue = Double -> FailIfSlower
FailIfSlower (Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0.0)
parseValue :: String -> Maybe FailIfSlower
parseValue = (Double -> FailIfSlower) -> Maybe Double -> Maybe FailIfSlower
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> FailIfSlower
FailIfSlower (Maybe Double -> Maybe FailIfSlower)
-> (String -> Maybe Double) -> String -> Maybe FailIfSlower
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe Double
parsePositivePercents
optionName :: Tagged FailIfSlower String
optionName = String -> Tagged FailIfSlower String
forall a. a -> Tagged FailIfSlower a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"fail-if-slower"
optionHelp :: Tagged FailIfSlower String
optionHelp = String -> Tagged FailIfSlower String
forall a. a -> Tagged FailIfSlower a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"Upper bound of acceptable slow down in percents. If a benchmark is unacceptably slower than baseline (see --baseline), it will be reported as failed."
newtype FailIfFaster = FailIfFaster Double
deriving
( FailIfFaster -> FailIfFaster -> Bool
(FailIfFaster -> FailIfFaster -> Bool)
-> (FailIfFaster -> FailIfFaster -> Bool) -> Eq FailIfFaster
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FailIfFaster -> FailIfFaster -> Bool
== :: FailIfFaster -> FailIfFaster -> Bool
$c/= :: FailIfFaster -> FailIfFaster -> Bool
/= :: FailIfFaster -> FailIfFaster -> Bool
Eq
, Eq FailIfFaster
Eq FailIfFaster =>
(FailIfFaster -> FailIfFaster -> Ordering)
-> (FailIfFaster -> FailIfFaster -> Bool)
-> (FailIfFaster -> FailIfFaster -> Bool)
-> (FailIfFaster -> FailIfFaster -> Bool)
-> (FailIfFaster -> FailIfFaster -> Bool)
-> (FailIfFaster -> FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster -> FailIfFaster)
-> Ord FailIfFaster
FailIfFaster -> FailIfFaster -> Bool
FailIfFaster -> FailIfFaster -> Ordering
FailIfFaster -> FailIfFaster -> FailIfFaster
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: FailIfFaster -> FailIfFaster -> Ordering
compare :: FailIfFaster -> FailIfFaster -> Ordering
$c< :: FailIfFaster -> FailIfFaster -> Bool
< :: FailIfFaster -> FailIfFaster -> Bool
$c<= :: FailIfFaster -> FailIfFaster -> Bool
<= :: FailIfFaster -> FailIfFaster -> Bool
$c> :: FailIfFaster -> FailIfFaster -> Bool
> :: FailIfFaster -> FailIfFaster -> Bool
$c>= :: FailIfFaster -> FailIfFaster -> Bool
>= :: FailIfFaster -> FailIfFaster -> Bool
$cmax :: FailIfFaster -> FailIfFaster -> FailIfFaster
max :: FailIfFaster -> FailIfFaster -> FailIfFaster
$cmin :: FailIfFaster -> FailIfFaster -> FailIfFaster
min :: FailIfFaster -> FailIfFaster -> FailIfFaster
Ord
, Key -> FailIfFaster -> ShowS
[FailIfFaster] -> ShowS
FailIfFaster -> String
(Key -> FailIfFaster -> ShowS)
-> (FailIfFaster -> String)
-> ([FailIfFaster] -> ShowS)
-> Show FailIfFaster
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Key -> FailIfFaster -> ShowS
showsPrec :: Key -> FailIfFaster -> ShowS
$cshow :: FailIfFaster -> String
show :: FailIfFaster -> String
$cshowList :: [FailIfFaster] -> ShowS
showList :: [FailIfFaster] -> ShowS
Show
, ReadPrec [FailIfFaster]
ReadPrec FailIfFaster
Key -> ReadS FailIfFaster
ReadS [FailIfFaster]
(Key -> ReadS FailIfFaster)
-> ReadS [FailIfFaster]
-> ReadPrec FailIfFaster
-> ReadPrec [FailIfFaster]
-> Read FailIfFaster
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Key -> ReadS FailIfFaster
readsPrec :: Key -> ReadS FailIfFaster
$creadList :: ReadS [FailIfFaster]
readList :: ReadS [FailIfFaster]
$creadPrec :: ReadPrec FailIfFaster
readPrec :: ReadPrec FailIfFaster
$creadListPrec :: ReadPrec [FailIfFaster]
readListPrec :: ReadPrec [FailIfFaster]
Read
, Integer -> FailIfFaster
FailIfFaster -> FailIfFaster
FailIfFaster -> FailIfFaster -> FailIfFaster
(FailIfFaster -> FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster)
-> (Integer -> FailIfFaster)
-> Num FailIfFaster
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: FailIfFaster -> FailIfFaster -> FailIfFaster
+ :: FailIfFaster -> FailIfFaster -> FailIfFaster
$c- :: FailIfFaster -> FailIfFaster -> FailIfFaster
- :: FailIfFaster -> FailIfFaster -> FailIfFaster
$c* :: FailIfFaster -> FailIfFaster -> FailIfFaster
* :: FailIfFaster -> FailIfFaster -> FailIfFaster
$cnegate :: FailIfFaster -> FailIfFaster
negate :: FailIfFaster -> FailIfFaster
$cabs :: FailIfFaster -> FailIfFaster
abs :: FailIfFaster -> FailIfFaster
$csignum :: FailIfFaster -> FailIfFaster
signum :: FailIfFaster -> FailIfFaster
$cfromInteger :: Integer -> FailIfFaster
fromInteger :: Integer -> FailIfFaster
Num
, Num FailIfFaster
Num FailIfFaster =>
(FailIfFaster -> FailIfFaster -> FailIfFaster)
-> (FailIfFaster -> FailIfFaster)
-> (Rational -> FailIfFaster)
-> Fractional FailIfFaster
Rational -> FailIfFaster
FailIfFaster -> FailIfFaster
FailIfFaster -> FailIfFaster -> FailIfFaster
forall a.
Num a =>
(a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
$c/ :: FailIfFaster -> FailIfFaster -> FailIfFaster
/ :: FailIfFaster -> FailIfFaster -> FailIfFaster
$crecip :: FailIfFaster -> FailIfFaster
recip :: FailIfFaster -> FailIfFaster
$cfromRational :: Rational -> FailIfFaster
fromRational :: Rational -> FailIfFaster
Fractional
)
instance IsOption FailIfFaster where
defaultValue :: FailIfFaster
defaultValue = Double -> FailIfFaster
FailIfFaster (Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0.0)
parseValue :: String -> Maybe FailIfFaster
parseValue = (Double -> FailIfFaster) -> Maybe Double -> Maybe FailIfFaster
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> FailIfFaster
FailIfFaster (Maybe Double -> Maybe FailIfFaster)
-> (String -> Maybe Double) -> String -> Maybe FailIfFaster
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe Double
parsePositivePercents
optionName :: Tagged FailIfFaster String
optionName = String -> Tagged FailIfFaster String
forall a. a -> Tagged FailIfFaster a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"fail-if-faster"
optionHelp :: Tagged FailIfFaster String
optionHelp = String -> Tagged FailIfFaster String
forall a. a -> Tagged FailIfFaster a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"Upper bound of acceptable speed up in percents. If a benchmark is unacceptably faster than baseline (see --baseline), it will be reported as failed."
parsePositivePercents :: String -> Maybe Double
parsePositivePercents :: String -> Maybe Double
parsePositivePercents String
xs = do
Double
x <- String -> Maybe Double
forall a. Read a => String -> Maybe a
safeRead String
xs
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0)
Double -> Maybe Double
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100)
instance IsOption TimeMode where
defaultValue :: TimeMode
defaultValue = TimeMode
CpuTime
parseValue :: String -> Maybe TimeMode
parseValue String
v = case String
v of
String
"cpu" -> TimeMode -> Maybe TimeMode
forall a. a -> Maybe a
Just TimeMode
CpuTime
String
"wall" -> TimeMode -> Maybe TimeMode
forall a. a -> Maybe a
Just TimeMode
WallTime
String
_ -> Maybe TimeMode
forall a. Maybe a
Nothing
optionName :: Tagged TimeMode String
optionName = String -> Tagged TimeMode String
forall a. a -> Tagged TimeMode a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"time-mode"
optionHelp :: Tagged TimeMode String
optionHelp = String -> Tagged TimeMode String
forall a. a -> Tagged TimeMode a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"Whether to measure CPU time (\"cpu\") or wall-clock time (\"wall\")"
showDefaultValue :: TimeMode -> Maybe String
showDefaultValue TimeMode
m = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ case TimeMode
m of
TimeMode
CpuTime -> String
"cpu"
TimeMode
WallTime -> String
"wall"
#endif
newtype Benchmarkable =
Benchmarkable
{ Benchmarkable -> Word64 -> IO ()
unBenchmarkable :: Word64 -> IO ()
}
#ifdef MIN_VERSION_tasty
supportsUnicode :: Bool
supportsUnicode :: Bool
supportsUnicode = Key -> ShowS
forall a. Key -> [a] -> [a]
take Key
3 (TextEncoding -> String
textEncodingName TextEncoding
enc) String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"UTF"
#if defined(mingw32_HOST_OS)
&& unsafePerformIO getConsoleOutputCP == 65001
#endif
where
enc :: TextEncoding
enc = IO TextEncoding -> TextEncoding
forall a. IO a -> a
unsafePerformIO IO TextEncoding
getLocaleEncoding
{-# NOINLINE supportsUnicode #-}
mu :: Char
mu :: Char
mu = if Bool
supportsUnicode then Char
'μ' else Char
'u'
pm :: String
pm :: String
pm = if Bool
supportsUnicode then String
" ± " else String
" +-"
showPicos3 :: Word64 -> String
showPicos3 :: Word64 -> String
showPicos3 Word64
i
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ps" Double
t
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e1 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f ns" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e3)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e3 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ns" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e3)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e4 = String -> Double -> Char -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f %cs" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e6) Char
mu
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e6 = String -> Double -> Char -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f %cs" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e6) Char
mu
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e7 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f ms" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e9)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e9 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ms" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e9)
| Bool
otherwise = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.2f s" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e12)
where
t :: Double
t = Word64 -> Double
word64ToDouble Word64
i
showPicos4 :: Word64 -> String
showPicos4 :: Word64 -> String
showPicos4 Word64
i
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ps" Double
t
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e1 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.2f ns" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e3)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e2 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.1f ns" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e3)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e3 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ns" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e3)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e4 = String -> Double -> Char -> String
forall r. PrintfType r => String -> r
printf String
"%4.2f %cs" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e6) Char
mu
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e5 = String -> Double -> Char -> String
forall r. PrintfType r => String -> r
printf String
"%4.1f %cs" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e6) Char
mu
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e6 = String -> Double -> Char -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f %cs" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e6) Char
mu
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e7 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.2f ms" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e9)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e8 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.1f ms" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e9)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
995e9 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f ms" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e9)
| Bool
otherwise = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%4.3f s" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e12)
where
t :: Double
t = Word64 -> Double
word64ToDouble Word64
i
showBytes :: Word64 -> String
showBytes :: Word64 -> String
showBytes Word64
i
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1000 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f B " Double
t
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
10189 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f KB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1023488 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f KB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1024)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
10433332 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f MB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1048576)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1048051712 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f MB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1048576)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
10683731149 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f GB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1073741824)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1073204953088 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f GB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1073741824)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
10940140696372 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f TB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1099511627776)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1098961871962112 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f TB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1099511627776)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
11202704073084108 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f PB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1125899906842624)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1125336956889202624 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f PB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1125899906842624)
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
11471568970838126592 = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.1f EB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1152921504606846976)
| Bool
otherwise = String -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%3.0f EB" (Double
t Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1152921504606846976)
where
t :: Double
t = Word64 -> Double
word64ToDouble Word64
i
#endif
data Measurement = Measurement
{ Measurement -> Word64
measTime :: !Word64
, Measurement -> Word64
measAllocs :: !Word64
, Measurement -> Word64
measCopied :: !Word64
, Measurement -> Word64
measMaxMem :: !Word64
} deriving (Key -> Measurement -> ShowS
[Measurement] -> ShowS
Measurement -> String
(Key -> Measurement -> ShowS)
-> (Measurement -> String)
-> ([Measurement] -> ShowS)
-> Show Measurement
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Key -> Measurement -> ShowS
showsPrec :: Key -> Measurement -> ShowS
$cshow :: Measurement -> String
show :: Measurement -> String
$cshowList :: [Measurement] -> ShowS
showList :: [Measurement] -> ShowS
Show, ReadPrec [Measurement]
ReadPrec Measurement
Key -> ReadS Measurement
ReadS [Measurement]
(Key -> ReadS Measurement)
-> ReadS [Measurement]
-> ReadPrec Measurement
-> ReadPrec [Measurement]
-> Read Measurement
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Key -> ReadS Measurement
readsPrec :: Key -> ReadS Measurement
$creadList :: ReadS [Measurement]
readList :: ReadS [Measurement]
$creadPrec :: ReadPrec Measurement
readPrec :: ReadPrec Measurement
$creadListPrec :: ReadPrec [Measurement]
readListPrec :: ReadPrec [Measurement]
Read)
data Estimate = Estimate
{ Estimate -> Measurement
estMean :: !Measurement
, Estimate -> Word64
estStdev :: !Word64
} deriving (Key -> Estimate -> ShowS
[Estimate] -> ShowS
Estimate -> String
(Key -> Estimate -> ShowS)
-> (Estimate -> String) -> ([Estimate] -> ShowS) -> Show Estimate
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Key -> Estimate -> ShowS
showsPrec :: Key -> Estimate -> ShowS
$cshow :: Estimate -> String
show :: Estimate -> String
$cshowList :: [Estimate] -> ShowS
showList :: [Estimate] -> ShowS
Show, ReadPrec [Estimate]
ReadPrec Estimate
Key -> ReadS Estimate
ReadS [Estimate]
(Key -> ReadS Estimate)
-> ReadS [Estimate]
-> ReadPrec Estimate
-> ReadPrec [Estimate]
-> Read Estimate
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Key -> ReadS Estimate
readsPrec :: Key -> ReadS Estimate
$creadList :: ReadS [Estimate]
readList :: ReadS [Estimate]
$creadPrec :: ReadPrec Estimate
readPrec :: ReadPrec Estimate
$creadListPrec :: ReadPrec [Estimate]
readListPrec :: ReadPrec [Estimate]
Read)
#ifdef MIN_VERSION_tasty
data WithLoHi a = WithLoHi
!a
!Double
!Double
deriving (Key -> WithLoHi a -> ShowS
[WithLoHi a] -> ShowS
WithLoHi a -> String
(Key -> WithLoHi a -> ShowS)
-> (WithLoHi a -> String)
-> ([WithLoHi a] -> ShowS)
-> Show (WithLoHi a)
forall a. Show a => Key -> WithLoHi a -> ShowS
forall a. Show a => [WithLoHi a] -> ShowS
forall a. Show a => WithLoHi a -> String
forall a.
(Key -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Key -> WithLoHi a -> ShowS
showsPrec :: Key -> WithLoHi a -> ShowS
$cshow :: forall a. Show a => WithLoHi a -> String
show :: WithLoHi a -> String
$cshowList :: forall a. Show a => [WithLoHi a] -> ShowS
showList :: [WithLoHi a] -> ShowS
Show, ReadPrec [WithLoHi a]
ReadPrec (WithLoHi a)
Key -> ReadS (WithLoHi a)
ReadS [WithLoHi a]
(Key -> ReadS (WithLoHi a))
-> ReadS [WithLoHi a]
-> ReadPrec (WithLoHi a)
-> ReadPrec [WithLoHi a]
-> Read (WithLoHi a)
forall a. Read a => ReadPrec [WithLoHi a]
forall a. Read a => ReadPrec (WithLoHi a)
forall a. Read a => Key -> ReadS (WithLoHi a)
forall a. Read a => ReadS [WithLoHi a]
forall a.
(Key -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Read a => Key -> ReadS (WithLoHi a)
readsPrec :: Key -> ReadS (WithLoHi a)
$creadList :: forall a. Read a => ReadS [WithLoHi a]
readList :: ReadS [WithLoHi a]
$creadPrec :: forall a. Read a => ReadPrec (WithLoHi a)
readPrec :: ReadPrec (WithLoHi a)
$creadListPrec :: forall a. Read a => ReadPrec [WithLoHi a]
readListPrec :: ReadPrec [WithLoHi a]
Read)
prettyEstimate :: Estimate -> String
prettyEstimate :: Estimate -> String
prettyEstimate (Estimate Measurement
m Word64
stdev) =
Word64 -> String
showPicos4 (Measurement -> Word64
measTime Measurement
m)
String -> ShowS
forall a. [a] -> [a] -> [a]
++ (if Word64
stdev Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 then String
" " else String
pm String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showPicos3 (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev))
prettyEstimateWithGC :: Estimate -> String
prettyEstimateWithGC :: Estimate -> String
prettyEstimateWithGC (Estimate Measurement
m Word64
stdev) =
Word64 -> String
showPicos4 (Measurement -> Word64
measTime Measurement
m)
String -> ShowS
forall a. [a] -> [a] -> [a]
++ (if Word64
stdev Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 then String
", " else String
pm String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showPicos3 (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
", ")
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showBytes (Measurement -> Word64
measAllocs Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" allocated, "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showBytes (Measurement -> Word64
measCopied Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" copied, "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showBytes (Measurement -> Word64
measMaxMem Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" peak memory"
csvEstimate :: Estimate -> String
csvEstimate :: Estimate -> String
csvEstimate (Estimate Measurement
m Word64
stdev) = Word64 -> String
forall a. Show a => a -> String
show (Measurement -> Word64
measTime Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev)
csvEstimateWithGC :: Estimate -> String
csvEstimateWithGC :: Estimate -> String
csvEstimateWithGC (Estimate Measurement
m Word64
stdev) = Word64 -> String
forall a. Show a => a -> String
show (Measurement -> Word64
measTime Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev)
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (Measurement -> Word64
measAllocs Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (Measurement -> Word64
measCopied Measurement
m) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (Measurement -> Word64
measMaxMem Measurement
m)
#endif
predict
:: Measurement
-> Measurement
-> Estimate
predict :: Measurement -> Measurement -> Estimate
predict (Measurement Word64
t1 Word64
a1 Word64
c1 Word64
m1) (Measurement Word64
t2 Word64
a2 Word64
c2 Word64
m2) = Estimate
{ estMean :: Measurement
estMean = Word64 -> Word64 -> Word64 -> Word64 -> Measurement
Measurement Word64
t (Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
fit Word64
a1 Word64
a2) (Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
fit Word64
c1 Word64
c2) (Word64 -> Word64 -> Word64
forall a. Ord a => a -> a -> a
max Word64
m1 Word64
m2)
, estStdev :: Word64
estStdev = Double -> Word64
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double -> Double
forall a. Floating a => a -> a
sqrt Double
d :: Double)
}
where
fit :: a -> a -> a
fit a
x1 a
x2 = a
x1 a -> a -> a
forall {a}. Integral a => a -> a -> a
`quot` a
5 a -> a -> a
forall a. Num a => a -> a -> a
+ a
2 a -> a -> a
forall a. Num a => a -> a -> a
* (a
x2 a -> a -> a
forall {a}. Integral a => a -> a -> a
`quot` a
5)
t :: Word64
t = Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
fit Word64
t1 Word64
t2
sqr :: a -> a
sqr a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
x
d :: Double
d = Double -> Double
forall {a}. Num a => a -> a
sqr (Word64 -> Double
word64ToDouble Word64
t1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Word64 -> Double
word64ToDouble Word64
t)
Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall {a}. Num a => a -> a
sqr (Word64 -> Double
word64ToDouble Word64
t2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Word64 -> Double
word64ToDouble Word64
t)
predictPerturbed :: Measurement -> Measurement -> Estimate
predictPerturbed :: Measurement -> Measurement -> Estimate
predictPerturbed Measurement
t1 Measurement
t2 = Estimate
{ estMean :: Measurement
estMean = Estimate -> Measurement
estMean (Measurement -> Measurement -> Estimate
predict Measurement
t1 Measurement
t2)
, estStdev :: Word64
estStdev = Word64 -> Word64 -> Word64
forall a. Ord a => a -> a -> a
max
(Estimate -> Word64
estStdev (Measurement -> Measurement -> Estimate
predict (Measurement -> Measurement
lo Measurement
t1) (Measurement -> Measurement
hi Measurement
t2)))
(Estimate -> Word64
estStdev (Measurement -> Measurement -> Estimate
predict (Measurement -> Measurement
hi Measurement
t1) (Measurement -> Measurement
lo Measurement
t2)))
}
where
prec :: Word64
prec = Word64 -> Word64 -> Word64
forall a. Ord a => a -> a -> a
max (Integer -> Word64
forall a. Num a => Integer -> a
fromInteger Integer
cpuTimePrecision) Word64
1000000000
hi :: Measurement -> Measurement
hi Measurement
meas = Measurement
meas { measTime = measTime meas + prec }
lo :: Measurement -> Measurement
lo Measurement
meas = Measurement
meas { measTime = measTime meas - prec }
hasGCStats :: Bool
#if MIN_VERSION_base(4,10,0)
hasGCStats :: Bool
hasGCStats = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO IO Bool
getRTSStatsEnabled
#else
hasGCStats = unsafePerformIO getGCStatsEnabled
#endif
getAllocsAndCopied :: IO (Word64, Word64, Word64)
getAllocsAndCopied :: IO (Word64, Word64, Word64)
getAllocsAndCopied = do
if Bool -> Bool
not Bool
hasGCStats then (Word64, Word64, Word64) -> IO (Word64, Word64, Word64)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64
0, Word64
0, Word64
0) else
#if MIN_VERSION_base(4,10,0)
(\RTSStats
s -> (RTSStats -> Word64
allocated_bytes RTSStats
s, RTSStats -> Word64
copied_bytes RTSStats
s, RTSStats -> Word64
max_mem_in_use_bytes RTSStats
s)) (RTSStats -> (Word64, Word64, Word64))
-> IO RTSStats -> IO (Word64, Word64, Word64)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO RTSStats
getRTSStats
#else
(\s -> (int64ToWord64 $ bytesAllocated s, int64ToWord64 $ bytesCopied s, int64ToWord64 $ peakMegabytesAllocated s * 1024 * 1024)) <$> getGCStats
#endif
getWallTimeSecs :: IO Double
#if MIN_VERSION_base(4,11,0)
getWallTimeSecs :: IO Double
getWallTimeSecs = IO Double
getMonotonicTime
#else
getWallTimeSecs = realToFrac <$> getPOSIXTime
#endif
getTimePicoSecs :: TimeMode -> IO Word64
getTimePicoSecs :: TimeMode -> IO Word64
getTimePicoSecs TimeMode
timeMode = case TimeMode
timeMode of
TimeMode
CpuTime -> Integer -> Word64
forall a. Num a => Integer -> a
fromInteger (Integer -> Word64) -> IO Integer -> IO Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Integer
getCPUTime
TimeMode
WallTime -> Double -> Word64
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Word64) -> (Double -> Double) -> Double -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double
1e12 Double -> Double -> Double
forall a. Num a => a -> a -> a
*) (Double -> Word64) -> IO Double -> IO Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Double
getWallTimeSecs
measure :: TimeMode -> Word64 -> Benchmarkable -> IO Measurement
measure :: TimeMode -> Word64 -> Benchmarkable -> IO Measurement
measure TimeMode
timeMode Word64
n (Benchmarkable Word64 -> IO ()
act) = do
let getTimePicoSecs' :: IO Word64
getTimePicoSecs' = TimeMode -> IO Word64
getTimePicoSecs TimeMode
timeMode
IO ()
performGC
Word64
startTime <- IO Word64
getTimePicoSecs'
(Word64
startAllocs, Word64
startCopied, Word64
startMaxMemInUse) <- IO (Word64, Word64, Word64)
getAllocsAndCopied
Word64 -> IO ()
act Word64
n
Word64
endTime <- IO Word64
getTimePicoSecs'
IO ()
performMinorGC
(Word64
endAllocs, Word64
endCopied, Word64
endMaxMemInUse) <- IO (Word64, Word64, Word64)
getAllocsAndCopied
let meas :: Measurement
meas = Measurement
{ measTime :: Word64
measTime = Word64
endTime Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
startTime
, measAllocs :: Word64
measAllocs = Word64
endAllocs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
startAllocs
, measCopied :: Word64
measCopied = Word64
endCopied Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
startCopied
, measMaxMem :: Word64
measMaxMem = Word64 -> Word64 -> Word64
forall a. Ord a => a -> a -> a
max Word64
endMaxMemInUse Word64
startMaxMemInUse
}
Measurement -> IO Measurement
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Measurement
meas
measureUntil
:: (Progress -> IO ())
-> TimeMode
-> Timeout
-> RelStDev
-> Benchmarkable
-> IO Estimate
measureUntil :: (Progress -> IO ())
-> TimeMode -> Timeout -> RelStDev -> Benchmarkable -> IO Estimate
measureUntil Progress -> IO ()
_ TimeMode
timeMode Timeout
_ (RelStDev Double
targetRelStDev) Benchmarkable
b
| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
targetRelStDev, Double
targetRelStDev Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 = do
Measurement
t1 <- TimeMode -> Word64 -> Benchmarkable -> IO Measurement
measure TimeMode
timeMode Word64
1 Benchmarkable
b
Estimate -> IO Estimate
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Estimate -> IO Estimate) -> Estimate -> IO Estimate
forall a b. (a -> b) -> a -> b
$ Estimate { estMean :: Measurement
estMean = Measurement
t1, estStdev :: Word64
estStdev = Word64
0 }
measureUntil Progress -> IO ()
yieldProgress TimeMode
timeMode Timeout
timeout (RelStDev Double
targetRelStDev) Benchmarkable
b = do
Measurement
t1 <- Word64 -> Benchmarkable -> IO Measurement
measure' Word64
1 Benchmarkable
b
Word64 -> Measurement -> Word64 -> IO Estimate
go Word64
1 Measurement
t1 Word64
0
where
measure' :: Word64 -> Benchmarkable -> IO Measurement
measure' = TimeMode -> Word64 -> Benchmarkable -> IO Measurement
measure TimeMode
timeMode
go :: Word64 -> Measurement -> Word64 -> IO Estimate
go :: Word64 -> Measurement -> Word64 -> IO Estimate
go Word64
n Measurement
t1 Word64
sumOfTs = do
Measurement
t2 <- Word64 -> Benchmarkable -> IO Measurement
measure' (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
n) Benchmarkable
b
let Estimate (Measurement Word64
meanN Word64
allocN Word64
copiedN Word64
maxMemN) Word64
stdevN = Measurement -> Measurement -> Estimate
predictPerturbed Measurement
t1 Measurement
t2
isTimeoutSoon :: Bool
isTimeoutSoon = case Timeout
timeout of
Timeout
NoTimeout -> Bool
False
Timeout Integer
micros String
_ -> (Word64
sumOfTs' Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
3 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Measurement -> Word64
measTime Measurement
t2) Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` (Word64
1000000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
10 Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` Word64
12) Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer -> Word64
forall a. Num a => Integer -> a
fromInteger Integer
micros
isStDevInTargetRange :: Bool
isStDevInTargetRange = Word64
stdevN Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Word64
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0 Double
targetRelStDev Double -> Double -> Double
forall a. Num a => a -> a -> a
* Word64 -> Double
word64ToDouble Word64
meanN)
scale :: Word64 -> Word64
scale = (Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` Word64
n)
sumOfTs' :: Word64
sumOfTs' = Word64
sumOfTs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Measurement -> Word64
measTime Measurement
t1
let scaledEstimate :: Estimate
scaledEstimate = Estimate
{ estMean :: Measurement
estMean = Word64 -> Word64 -> Word64 -> Word64 -> Measurement
Measurement (Word64 -> Word64
scale Word64
meanN) (Word64 -> Word64
scale Word64
allocN) (Word64 -> Word64
scale Word64
copiedN) Word64
maxMemN
, estStdev :: Word64
estStdev = Word64 -> Word64
scale Word64
stdevN }
#ifdef MIN_VERSION_tasty
Progress -> IO ()
yieldProgress (Progress -> IO ()) -> Progress -> IO ()
forall a b. (a -> b) -> a -> b
$ Progress
{ progressText :: String
progressText = Estimate -> String
prettyEstimate Estimate
scaledEstimate
, progressPercent :: Float
progressPercent = Float
0.0
}
#else
yieldProgress ()
#endif
if Bool
isStDevInTargetRange Bool -> Bool -> Bool
|| Bool
isTimeoutSoon
then Estimate -> IO Estimate
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Estimate
scaledEstimate
else Word64 -> Measurement -> Word64 -> IO Estimate
go (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
n) Measurement
t2 Word64
sumOfTs'
measureCpuTime :: Timeout -> RelStDev -> Benchmarkable -> IO Double
measureCpuTime :: Timeout -> RelStDev -> Benchmarkable -> IO Double
measureCpuTime = ((((Double, Double) -> Double) -> IO (Double, Double) -> IO Double
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Double, Double) -> Double
forall a b. (a, b) -> a
fst (IO (Double, Double) -> IO Double)
-> (Benchmarkable -> IO (Double, Double))
-> Benchmarkable
-> IO Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Benchmarkable -> IO (Double, Double))
-> Benchmarkable -> IO Double)
-> (RelStDev -> Benchmarkable -> IO (Double, Double))
-> RelStDev
-> Benchmarkable
-> IO Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((RelStDev -> Benchmarkable -> IO (Double, Double))
-> RelStDev -> Benchmarkable -> IO Double)
-> (Timeout -> RelStDev -> Benchmarkable -> IO (Double, Double))
-> Timeout
-> RelStDev
-> Benchmarkable
-> IO Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Timeout -> RelStDev -> Benchmarkable -> IO (Double, Double)
measureCpuTimeAndStDev
measureCpuTimeAndStDev :: Timeout -> RelStDev -> Benchmarkable -> IO (Double, Double)
measureCpuTimeAndStDev :: Timeout -> RelStDev -> Benchmarkable -> IO (Double, Double)
measureCpuTimeAndStDev
= (((Estimate -> (Double, Double))
-> IO Estimate -> IO (Double, Double)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Estimate
x ->
( Word64 -> Double
word64ToDouble (Measurement -> Word64
measTime (Estimate -> Measurement
estMean Estimate
x)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e12
, Word64 -> Double
word64ToDouble (Estimate -> Word64
estStdev Estimate
x) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1e12
)) (IO Estimate -> IO (Double, Double))
-> (Benchmarkable -> IO Estimate)
-> Benchmarkable
-> IO (Double, Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Benchmarkable -> IO Estimate)
-> Benchmarkable -> IO (Double, Double))
-> (RelStDev -> Benchmarkable -> IO Estimate)
-> RelStDev
-> Benchmarkable
-> IO (Double, Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)
((RelStDev -> Benchmarkable -> IO Estimate)
-> RelStDev -> Benchmarkable -> IO (Double, Double))
-> (Timeout -> RelStDev -> Benchmarkable -> IO Estimate)
-> Timeout
-> RelStDev
-> Benchmarkable
-> IO (Double, Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Progress -> IO ())
-> TimeMode -> Timeout -> RelStDev -> Benchmarkable -> IO Estimate
measureUntil (IO () -> Progress -> IO ()
forall a b. a -> b -> a
const (IO () -> Progress -> IO ()) -> IO () -> Progress -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) TimeMode
CpuTime
#ifdef MIN_VERSION_tasty
instance IsTest Benchmarkable where
testOptions :: Tagged Benchmarkable [OptionDescription]
testOptions = [OptionDescription] -> Tagged Benchmarkable [OptionDescription]
forall a. a -> Tagged Benchmarkable a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
[ Proxy RelStDev -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy RelStDev
forall {k} (t :: k). Proxy t
Proxy :: Proxy RelStDev)
, Proxy FailIfSlower -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy FailIfSlower
forall {k} (t :: k). Proxy t
Proxy :: Proxy FailIfSlower)
, Proxy FailIfFaster -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy FailIfFaster
forall {k} (t :: k). Proxy t
Proxy :: Proxy FailIfFaster)
, Proxy TimeMode -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy TimeMode
forall {k} (t :: k). Proxy t
Proxy :: Proxy TimeMode)
]
run :: OptionSet -> Benchmarkable -> (Progress -> IO ()) -> IO Result
run OptionSet
opts Benchmarkable
b Progress -> IO ()
yieldProgress = case NumThreads -> Key
getNumThreads (OptionSet -> NumThreads
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts) of
Key
1 -> do
let timeMode :: TimeMode
timeMode = OptionSet -> TimeMode
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts
Estimate
est <- (Progress -> IO ())
-> TimeMode -> Timeout -> RelStDev -> Benchmarkable -> IO Estimate
measureUntil Progress -> IO ()
yieldProgress TimeMode
timeMode (OptionSet -> Timeout
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts) (OptionSet -> RelStDev
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts) Benchmarkable
b
let FailIfSlower Double
ifSlower = OptionSet -> FailIfSlower
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts
FailIfFaster Double
ifFaster = OptionSet -> FailIfFaster
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts
Result -> IO Result
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Result -> IO Result) -> Result -> IO Result
forall a b. (a -> b) -> a -> b
$ String -> Result
testPassed (String -> Result) -> String -> Result
forall a b. (a -> b) -> a -> b
$ WithLoHi Estimate -> String
forall a. Show a => a -> String
show (Estimate -> Double -> Double -> WithLoHi Estimate
forall a. a -> Double -> Double -> WithLoHi a
WithLoHi Estimate
est (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
ifFaster) (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
ifSlower))
Key
_ -> Result -> IO Result
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Result -> IO Result) -> Result -> IO Result
forall a b. (a -> b) -> a -> b
$ String -> Result
testFailed String
"Benchmarks must not be run concurrently. Please pass -j1 and/or avoid +RTS -N."
bench :: String -> Benchmarkable -> Benchmark
bench :: String -> Benchmarkable -> Benchmark
bench = String -> Benchmarkable -> Benchmark
forall t. IsTest t => String -> t -> Benchmark
singleTest
bgroup :: String -> [Benchmark] -> Benchmark
bgroup :: String -> [Benchmark] -> Benchmark
bgroup = String -> [Benchmark] -> Benchmark
testGroup
bcompare
:: String
-> Benchmark
-> Benchmark
bcompare :: String -> Benchmark -> Benchmark
bcompare = Double -> Double -> String -> Benchmark -> Benchmark
bcompareWithin (-Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
0) (Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
0)
bcompareWithin
:: Double
-> Double
-> String
-> Benchmark
-> Benchmark
bcompareWithin :: Double -> Double -> String -> Benchmark -> Benchmark
bcompareWithin Double
lo Double
hi String
s = case String -> Maybe Expr
parseExpr String
s of
Maybe Expr
Nothing -> String -> Benchmark -> Benchmark
forall a. HasCallStack => String -> a
error (String -> Benchmark -> Benchmark)
-> String -> Benchmark -> Benchmark
forall a b. (a -> b) -> a -> b
$ String
"Could not parse bcompare pattern " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s
Just Expr
e -> DependencyType -> Expr -> Benchmark -> Benchmark
after_ DependencyType
AllSucceed (Expr -> Expr -> Expr
And (String -> Expr
StringLit (String
bcomparePrefix String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Double, Double) -> String
forall a. Show a => a -> String
show (Double
lo, Double
hi))) Expr
e)
bcomparePrefix :: String
bcomparePrefix :: String
bcomparePrefix = String
"tasty-bench"
type Benchmark = TestTree
defaultMain :: [Benchmark] -> IO ()
defaultMain :: [Benchmark] -> IO ()
defaultMain [Benchmark]
bs = do
let act :: IO ()
act = [Benchmark] -> IO ()
defaultMain' [Benchmark]
bs
IO () -> IO ()
forall a. IO a -> IO a
bracketUtf8 IO ()
act
bracketUtf8 :: IO a -> IO a
bracketUtf8 :: forall a. IO a -> IO a
bracketUtf8 IO a
act = do
TextEncoding
prevLocaleEnc <- IO TextEncoding
getLocaleEncoding
#if defined(mingw32_HOST_OS)
codePage <- getConsoleOutputCP
bracket_
(setLocaleEncoding utf8 >> setConsoleOutputCP 65001)
(setLocaleEncoding prevLocaleEnc >> setConsoleOutputCP codePage)
act
#else
IO () -> IO () -> IO a -> IO a
forall a b c. IO a -> IO b -> IO c -> IO c
bracket_
(TextEncoding -> IO ()
setLocaleEncoding TextEncoding
utf8)
(TextEncoding -> IO ()
setLocaleEncoding TextEncoding
prevLocaleEnc)
IO a
act
#endif
defaultMain' :: [Benchmark] -> IO ()
defaultMain' :: [Benchmark] -> IO ()
defaultMain' [Benchmark]
bs = do
IO ()
installSignalHandlers
let b :: Benchmark
b = String -> [Benchmark] -> Benchmark
testGroup String
"All" [Benchmark]
bs
OptionSet
opts <- [Ingredient] -> Benchmark -> IO OptionSet
parseOptions [Ingredient]
benchIngredients Benchmark
b
let opts' :: OptionSet
opts' = NumThreads -> OptionSet -> OptionSet
forall v. IsOption v => v -> OptionSet -> OptionSet
setOption (Key -> NumThreads
NumThreads Key
1) OptionSet
opts
#if MIN_VERSION_tasty(1,5,0)
opts'' :: OptionSet
opts'' = MinDurationToReport -> OptionSet -> OptionSet
forall v. IsOption v => v -> OptionSet -> OptionSet
setOption (Integer -> MinDurationToReport
MinDurationToReport Integer
1000000000000) OptionSet
opts'
#else
opts'' = opts'
#endif
case [Ingredient] -> OptionSet -> Benchmark -> Maybe (IO Bool)
tryIngredients [Ingredient]
benchIngredients OptionSet
opts'' Benchmark
b of
Maybe (IO Bool)
Nothing -> IO ()
forall a. IO a
exitFailure
Just IO Bool
act -> IO Bool
act IO Bool -> (Bool -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
x -> if Bool
x then IO ()
forall a. IO a
exitSuccess else IO ()
forall a. IO a
exitFailure
benchIngredients :: [Ingredient]
benchIngredients :: [Ingredient]
benchIngredients = [Ingredient
listingTests, Ingredient -> Ingredient -> Ingredient
composeReporters Ingredient
consoleBenchReporter (Ingredient -> Ingredient -> Ingredient
composeReporters Ingredient
csvReporter Ingredient
svgReporter)]
#endif
funcToBench :: forall a b c. (b -> c) -> (a -> b) -> a -> Benchmarkable
funcToBench :: forall a b c. (b -> c) -> (a -> b) -> a -> Benchmarkable
funcToBench b -> c
frc = ((Word64 -> IO ()) -> Benchmarkable
Benchmarkable ((Word64 -> IO ()) -> Benchmarkable)
-> (a -> Word64 -> IO ()) -> a -> Benchmarkable
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((a -> Word64 -> IO ()) -> a -> Benchmarkable)
-> ((a -> b) -> a -> Word64 -> IO ())
-> (a -> b)
-> a
-> Benchmarkable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SPEC -> (a -> b) -> a -> Word64 -> IO ()
funcToBenchLoop SPEC
SPEC
where
funcToBenchLoop :: SPEC -> (a -> b) -> a -> Word64 -> IO ()
funcToBenchLoop :: SPEC -> (a -> b) -> a -> Word64 -> IO ()
funcToBenchLoop !SPEC
_ a -> b
f a
x Word64
n
| Word64
n Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
c
_ <- c -> IO c
forall a. a -> IO a
evaluate (b -> c
frc (a -> b
f a
x))
SPEC -> (a -> b) -> a -> Word64 -> IO ()
funcToBenchLoop SPEC
SPEC a -> b
f a
x (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1)
{-# INLINE funcToBench #-}
nf :: NFData b => (a -> b) -> a -> Benchmarkable
nf :: forall b a. NFData b => (a -> b) -> a -> Benchmarkable
nf = (b -> ()) -> (a -> b) -> a -> Benchmarkable
forall a b c. (b -> c) -> (a -> b) -> a -> Benchmarkable
funcToBench b -> ()
forall a. NFData a => a -> ()
rnf
{-# INLINE nf #-}
whnf :: (a -> b) -> a -> Benchmarkable
whnf :: forall a b. (a -> b) -> a -> Benchmarkable
whnf = (b -> b) -> (a -> b) -> a -> Benchmarkable
forall a b c. (b -> c) -> (a -> b) -> a -> Benchmarkable
funcToBench b -> b
forall a. a -> a
id
{-# INLINE whnf #-}
ioToBench :: (b -> c) -> IO b -> Benchmarkable
ioToBench :: forall b c. (b -> c) -> IO b -> Benchmarkable
ioToBench b -> c
frc IO b
act = (Word64 -> IO ()) -> Benchmarkable
Benchmarkable (SPEC -> Word64 -> IO ()
ioToBenchLoop SPEC
SPEC)
where
ioToBenchLoop :: SPEC -> Word64 -> IO ()
ioToBenchLoop :: SPEC -> Word64 -> IO ()
ioToBenchLoop !SPEC
_ Word64
n
| Word64
n Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
b
val <- IO b
act
c
_ <- c -> IO c
forall a. a -> IO a
evaluate (b -> c
frc b
val)
SPEC -> Word64 -> IO ()
ioToBenchLoop SPEC
SPEC (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1)
{-# INLINE ioToBench #-}
nfIO :: NFData a => IO a -> Benchmarkable
nfIO :: forall a. NFData a => IO a -> Benchmarkable
nfIO = (a -> ()) -> IO a -> Benchmarkable
forall b c. (b -> c) -> IO b -> Benchmarkable
ioToBench a -> ()
forall a. NFData a => a -> ()
rnf
{-# INLINE nfIO #-}
whnfIO :: IO a -> Benchmarkable
whnfIO :: forall a. IO a -> Benchmarkable
whnfIO = (a -> a) -> IO a -> Benchmarkable
forall b c. (b -> c) -> IO b -> Benchmarkable
ioToBench a -> a
forall a. a -> a
id
{-# INLINE whnfIO #-}
ioFuncToBench :: forall a b c. (b -> c) -> (a -> IO b) -> a -> Benchmarkable
ioFuncToBench :: forall a b c. (b -> c) -> (a -> IO b) -> a -> Benchmarkable
ioFuncToBench b -> c
frc = ((Word64 -> IO ()) -> Benchmarkable
Benchmarkable ((Word64 -> IO ()) -> Benchmarkable)
-> (a -> Word64 -> IO ()) -> a -> Benchmarkable
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((a -> Word64 -> IO ()) -> a -> Benchmarkable)
-> ((a -> IO b) -> a -> Word64 -> IO ())
-> (a -> IO b)
-> a
-> Benchmarkable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SPEC -> (a -> IO b) -> a -> Word64 -> IO ()
ioFuncToBenchLoop SPEC
SPEC
where
ioFuncToBenchLoop :: SPEC -> (a -> IO b) -> a -> Word64 -> IO ()
ioFuncToBenchLoop :: SPEC -> (a -> IO b) -> a -> Word64 -> IO ()
ioFuncToBenchLoop !SPEC
_ a -> IO b
f a
x Word64
n
| Word64
n Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
b
val <- a -> IO b
f a
x
c
_ <- c -> IO c
forall a. a -> IO a
evaluate (b -> c
frc b
val)
SPEC -> (a -> IO b) -> a -> Word64 -> IO ()
ioFuncToBenchLoop SPEC
SPEC a -> IO b
f a
x (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1)
{-# INLINE ioFuncToBench #-}
nfAppIO :: NFData b => (a -> IO b) -> a -> Benchmarkable
nfAppIO :: forall b a. NFData b => (a -> IO b) -> a -> Benchmarkable
nfAppIO = (b -> ()) -> (a -> IO b) -> a -> Benchmarkable
forall a b c. (b -> c) -> (a -> IO b) -> a -> Benchmarkable
ioFuncToBench b -> ()
forall a. NFData a => a -> ()
rnf
{-# INLINE nfAppIO #-}
whnfAppIO :: (a -> IO b) -> a -> Benchmarkable
whnfAppIO :: forall a b. (a -> IO b) -> a -> Benchmarkable
whnfAppIO = (b -> b) -> (a -> IO b) -> a -> Benchmarkable
forall a b c. (b -> c) -> (a -> IO b) -> a -> Benchmarkable
ioFuncToBench b -> b
forall a. a -> a
id
{-# INLINE whnfAppIO #-}
#ifdef MIN_VERSION_tasty
env :: NFData env => IO env -> (env -> Benchmark) -> Benchmark
env :: forall env. NFData env => IO env -> (env -> Benchmark) -> Benchmark
env IO env
res = IO env -> (env -> IO ()) -> (env -> Benchmark) -> Benchmark
forall env a.
NFData env =>
IO env -> (env -> IO a) -> (env -> Benchmark) -> Benchmark
envWithCleanup IO env
res (IO () -> env -> IO ()
forall a b. a -> b -> a
const (IO () -> env -> IO ()) -> IO () -> env -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
envWithCleanup :: NFData env => IO env -> (env -> IO a) -> (env -> Benchmark) -> Benchmark
envWithCleanup :: forall env a.
NFData env =>
IO env -> (env -> IO a) -> (env -> Benchmark) -> Benchmark
envWithCleanup IO env
res env -> IO a
fin env -> Benchmark
f = IO env -> (env -> IO ()) -> (IO env -> Benchmark) -> Benchmark
forall a. IO a -> (a -> IO ()) -> (IO a -> Benchmark) -> Benchmark
withResource
(IO env
res IO env -> (env -> IO env) -> IO env
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= env -> IO env
forall a. a -> IO a
evaluate (env -> IO env) -> (env -> env) -> env -> IO env
forall b c a. (b -> c) -> (a -> b) -> a -> c
. env -> env
forall a. NFData a => a -> a
force)
(IO a -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO a -> IO ()) -> (env -> IO a) -> env -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. env -> IO a
fin)
(env -> Benchmark
f (env -> Benchmark) -> (IO env -> env) -> IO env -> Benchmark
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO env -> env
forall a. IO a -> a
unsafePerformIO)
newtype CsvPath = CsvPath FilePath
deriving
( CsvPath -> CsvPath -> Bool
(CsvPath -> CsvPath -> Bool)
-> (CsvPath -> CsvPath -> Bool) -> Eq CsvPath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CsvPath -> CsvPath -> Bool
== :: CsvPath -> CsvPath -> Bool
$c/= :: CsvPath -> CsvPath -> Bool
/= :: CsvPath -> CsvPath -> Bool
Eq
, Eq CsvPath
Eq CsvPath =>
(CsvPath -> CsvPath -> Ordering)
-> (CsvPath -> CsvPath -> Bool)
-> (CsvPath -> CsvPath -> Bool)
-> (CsvPath -> CsvPath -> Bool)
-> (CsvPath -> CsvPath -> Bool)
-> (CsvPath -> CsvPath -> CsvPath)
-> (CsvPath -> CsvPath -> CsvPath)
-> Ord CsvPath
CsvPath -> CsvPath -> Bool
CsvPath -> CsvPath -> Ordering
CsvPath -> CsvPath -> CsvPath
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: CsvPath -> CsvPath -> Ordering
compare :: CsvPath -> CsvPath -> Ordering
$c< :: CsvPath -> CsvPath -> Bool
< :: CsvPath -> CsvPath -> Bool
$c<= :: CsvPath -> CsvPath -> Bool
<= :: CsvPath -> CsvPath -> Bool
$c> :: CsvPath -> CsvPath -> Bool
> :: CsvPath -> CsvPath -> Bool
$c>= :: CsvPath -> CsvPath -> Bool
>= :: CsvPath -> CsvPath -> Bool
$cmax :: CsvPath -> CsvPath -> CsvPath
max :: CsvPath -> CsvPath -> CsvPath
$cmin :: CsvPath -> CsvPath -> CsvPath
min :: CsvPath -> CsvPath -> CsvPath
Ord
)
instance IsOption (Maybe CsvPath) where
defaultValue :: Maybe CsvPath
defaultValue = Maybe CsvPath
forall a. Maybe a
Nothing
parseValue :: String -> Maybe (Maybe CsvPath)
parseValue = Maybe CsvPath -> Maybe (Maybe CsvPath)
forall a. a -> Maybe a
Just (Maybe CsvPath -> Maybe (Maybe CsvPath))
-> (String -> Maybe CsvPath) -> String -> Maybe (Maybe CsvPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsvPath -> Maybe CsvPath
forall a. a -> Maybe a
Just (CsvPath -> Maybe CsvPath)
-> (String -> CsvPath) -> String -> Maybe CsvPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> CsvPath
CsvPath
optionName :: Tagged (Maybe CsvPath) String
optionName = String -> Tagged (Maybe CsvPath) String
forall a. a -> Tagged (Maybe CsvPath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"csv"
optionHelp :: Tagged (Maybe CsvPath) String
optionHelp = String -> Tagged (Maybe CsvPath) String
forall a. a -> Tagged (Maybe CsvPath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"File to write results in CSV format"
csvReporter :: Ingredient
csvReporter :: Ingredient
csvReporter = [OptionDescription]
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
TestReporter [Proxy (Maybe CsvPath) -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy (Maybe CsvPath)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (Maybe CsvPath))] ((OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient)
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
forall a b. (a -> b) -> a -> b
$
\OptionSet
opts Benchmark
tree -> do
CsvPath String
path <- OptionSet -> Maybe CsvPath
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts
let names :: [String]
names = OptionSet -> Benchmark -> [String]
testsNames OptionSet
opts Benchmark
tree
namesMap :: IntMap String
namesMap = [(Key, String)] -> IntMap String
forall a. [(Key, a)] -> IntMap a
IM.fromDistinctAscList ([(Key, String)] -> IntMap String)
-> [(Key, String)] -> IntMap String
forall a b. (a -> b) -> a -> b
$ [Key] -> [String] -> [(Key, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Key
0..] [String]
names
(StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> (StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
forall a b. (a -> b) -> a -> b
$ \StatusMap
smap -> do
case [String] -> Maybe String
forall a. Ord a => [a] -> Maybe a
findNonUniqueElement [String]
names of
Maybe String
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just String
name -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"CSV report cannot proceed, because name '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"' corresponds to two or more benchmarks. Please disambiguate them."
IO ()
forall a. IO a
exitFailure
let augmented :: IntMap (String, TVar Status)
augmented = (String -> TVar Status -> (String, TVar Status))
-> IntMap String -> StatusMap -> IntMap (String, TVar Status)
forall a b c. (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c
IM.intersectionWith (,) IntMap String
namesMap StatusMap
smap
IO Handle -> (Handle -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
(do
Handle
h <- String -> IOMode -> IO Handle
openFile String
path IOMode
WriteMode
Handle -> BufferMode -> IO ()
hSetBuffering Handle
h BufferMode
LineBuffering
Handle -> String -> IO ()
hPutStrLn Handle
h (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Name,Mean (ps),2*Stdev (ps)" String -> ShowS
forall a. [a] -> [a] -> [a]
++
(if Bool
hasGCStats then String
",Allocated,Copied,Peak Memory" else String
"")
Handle -> IO Handle
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Handle
h
)
Handle -> IO ()
hClose
(Handle -> IntMap (String, TVar Status) -> IO ()
`csvOutput` IntMap (String, TVar Status)
augmented)
(Double -> IO Bool) -> IO (Double -> IO Bool)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Double -> IO Bool) -> IO (Double -> IO Bool))
-> (Double -> IO Bool) -> IO (Double -> IO Bool)
forall a b. (a -> b) -> a -> b
$ IO Bool -> Double -> IO Bool
forall a b. a -> b -> a
const (IO Bool -> Double -> IO Bool) -> IO Bool -> Double -> IO Bool
forall a b. (a -> b) -> a -> b
$ StatusMap -> IO Bool
isSuccessful StatusMap
smap
findNonUniqueElement :: Ord a => [a] -> Maybe a
findNonUniqueElement :: forall a. Ord a => [a] -> Maybe a
findNonUniqueElement = Set a -> [a] -> Maybe a
forall {a}. Ord a => Set a -> [a] -> Maybe a
go Set a
forall a. Set a
S.empty
where
go :: Set a -> [a] -> Maybe a
go Set a
_ [] = Maybe a
forall a. Maybe a
Nothing
go Set a
acc (a
x : [a]
xs)
| a
x a -> Set a -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set a
acc = a -> Maybe a
forall a. a -> Maybe a
Just a
x
| Bool
otherwise = Set a -> [a] -> Maybe a
go (a -> Set a -> Set a
forall a. Ord a => a -> Set a -> Set a
S.insert a
x Set a
acc) [a]
xs
csvOutput :: Handle -> IntMap (TestName, TVar Status) -> IO ()
csvOutput :: Handle -> IntMap (String, TVar Status) -> IO ()
csvOutput Handle
h = ((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status) -> IO ())
-> ((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status)
-> IO ()
forall a b. (a -> b) -> a -> b
$ \(String
name, TVar Status
tv) -> do
let csv :: Estimate -> String
csv = if Bool
hasGCStats then Estimate -> String
csvEstimateWithGC else Estimate -> String
csvEstimate
Result
r <- STM Result -> IO Result
forall a. STM a -> IO a
atomically (STM Result -> IO Result) -> STM Result -> IO Result
forall a b. (a -> b) -> a -> b
$ TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
tv STM Status -> (Status -> STM Result) -> STM Result
forall a b. STM a -> (a -> STM b) -> STM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Status
s -> case Status
s of Done Result
r -> Result -> STM Result
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Result
r; Status
_ -> STM Result
forall a. STM a
retry
case String -> Maybe (WithLoHi Estimate)
forall a. Read a => String -> Maybe a
safeRead (Result -> String
resultDescription Result
r) of
Maybe (WithLoHi Estimate)
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just (WithLoHi Estimate
est Double
_ Double
_) -> do
String
msg <- String -> IO String
formatMessage (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ Estimate -> String
csv Estimate
est
Handle -> String -> IO ()
hPutStrLn Handle
h (ShowS
encodeCsv String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
',' Char -> ShowS
forall a. a -> [a] -> [a]
: String
msg)
encodeCsv :: String -> String
encodeCsv :: ShowS
encodeCsv String
xs
| (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
xs) String
",\"\n\r"
= Char
'"' Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
go String
xs
| Bool
otherwise = String
xs
where
go :: ShowS
go [] = Char
'"' Char -> ShowS
forall a. a -> [a] -> [a]
: []
go (Char
'"' : String
ys) = Char
'"' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
'"' Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
go String
ys
go (Char
y : String
ys) = Char
y Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
go String
ys
newtype SvgPath = SvgPath FilePath
deriving
( SvgPath -> SvgPath -> Bool
(SvgPath -> SvgPath -> Bool)
-> (SvgPath -> SvgPath -> Bool) -> Eq SvgPath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SvgPath -> SvgPath -> Bool
== :: SvgPath -> SvgPath -> Bool
$c/= :: SvgPath -> SvgPath -> Bool
/= :: SvgPath -> SvgPath -> Bool
Eq
, Eq SvgPath
Eq SvgPath =>
(SvgPath -> SvgPath -> Ordering)
-> (SvgPath -> SvgPath -> Bool)
-> (SvgPath -> SvgPath -> Bool)
-> (SvgPath -> SvgPath -> Bool)
-> (SvgPath -> SvgPath -> Bool)
-> (SvgPath -> SvgPath -> SvgPath)
-> (SvgPath -> SvgPath -> SvgPath)
-> Ord SvgPath
SvgPath -> SvgPath -> Bool
SvgPath -> SvgPath -> Ordering
SvgPath -> SvgPath -> SvgPath
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: SvgPath -> SvgPath -> Ordering
compare :: SvgPath -> SvgPath -> Ordering
$c< :: SvgPath -> SvgPath -> Bool
< :: SvgPath -> SvgPath -> Bool
$c<= :: SvgPath -> SvgPath -> Bool
<= :: SvgPath -> SvgPath -> Bool
$c> :: SvgPath -> SvgPath -> Bool
> :: SvgPath -> SvgPath -> Bool
$c>= :: SvgPath -> SvgPath -> Bool
>= :: SvgPath -> SvgPath -> Bool
$cmax :: SvgPath -> SvgPath -> SvgPath
max :: SvgPath -> SvgPath -> SvgPath
$cmin :: SvgPath -> SvgPath -> SvgPath
min :: SvgPath -> SvgPath -> SvgPath
Ord
)
instance IsOption (Maybe SvgPath) where
defaultValue :: Maybe SvgPath
defaultValue = Maybe SvgPath
forall a. Maybe a
Nothing
parseValue :: String -> Maybe (Maybe SvgPath)
parseValue = Maybe SvgPath -> Maybe (Maybe SvgPath)
forall a. a -> Maybe a
Just (Maybe SvgPath -> Maybe (Maybe SvgPath))
-> (String -> Maybe SvgPath) -> String -> Maybe (Maybe SvgPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SvgPath -> Maybe SvgPath
forall a. a -> Maybe a
Just (SvgPath -> Maybe SvgPath)
-> (String -> SvgPath) -> String -> Maybe SvgPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> SvgPath
SvgPath
optionName :: Tagged (Maybe SvgPath) String
optionName = String -> Tagged (Maybe SvgPath) String
forall a. a -> Tagged (Maybe SvgPath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"svg"
optionHelp :: Tagged (Maybe SvgPath) String
optionHelp = String -> Tagged (Maybe SvgPath) String
forall a. a -> Tagged (Maybe SvgPath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"File to plot results in SVG format"
svgReporter :: Ingredient
svgReporter :: Ingredient
svgReporter = [OptionDescription]
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
TestReporter [Proxy (Maybe SvgPath) -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy (Maybe SvgPath)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (Maybe SvgPath))] ((OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient)
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
forall a b. (a -> b) -> a -> b
$
\OptionSet
opts Benchmark
tree -> do
SvgPath String
path <- OptionSet -> Maybe SvgPath
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts
let names :: [String]
names = OptionSet -> Benchmark -> [String]
testsNames OptionSet
opts Benchmark
tree
namesMap :: IntMap String
namesMap = [(Key, String)] -> IntMap String
forall a. [(Key, a)] -> IntMap a
IM.fromDistinctAscList ([(Key, String)] -> IntMap String)
-> [(Key, String)] -> IntMap String
forall a b. (a -> b) -> a -> b
$ [Key] -> [String] -> [(Key, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Key
0..] [String]
names
(StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> (StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
forall a b. (a -> b) -> a -> b
$ \StatusMap
smap -> do
IORef [(String, Estimate)]
ref <- [(String, Estimate)] -> IO (IORef [(String, Estimate)])
forall a. a -> IO (IORef a)
newIORef []
IORef [(String, Estimate)] -> IntMap (String, TVar Status) -> IO ()
svgCollect IORef [(String, Estimate)]
ref ((String -> TVar Status -> (String, TVar Status))
-> IntMap String -> StatusMap -> IntMap (String, TVar Status)
forall a b c. (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c
IM.intersectionWith (,) IntMap String
namesMap StatusMap
smap)
[(String, Estimate)]
res <- IORef [(String, Estimate)] -> IO [(String, Estimate)]
forall a. IORef a -> IO a
readIORef IORef [(String, Estimate)]
ref
String -> String -> IO ()
writeFile String
path ([(String, Estimate)] -> String
svgRender ([(String, Estimate)] -> [(String, Estimate)]
forall a. [a] -> [a]
reverse [(String, Estimate)]
res))
(Double -> IO Bool) -> IO (Double -> IO Bool)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Double -> IO Bool) -> IO (Double -> IO Bool))
-> (Double -> IO Bool) -> IO (Double -> IO Bool)
forall a b. (a -> b) -> a -> b
$ IO Bool -> Double -> IO Bool
forall a b. a -> b -> a
const (IO Bool -> Double -> IO Bool) -> IO Bool -> Double -> IO Bool
forall a b. (a -> b) -> a -> b
$ StatusMap -> IO Bool
isSuccessful StatusMap
smap
isSuccessful :: StatusMap -> IO Bool
isSuccessful :: StatusMap -> IO Bool
isSuccessful = [TVar Status] -> IO Bool
go ([TVar Status] -> IO Bool)
-> (StatusMap -> [TVar Status]) -> StatusMap -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StatusMap -> [TVar Status]
forall a. IntMap a -> [a]
IM.elems
where
go :: [TVar Status] -> IO Bool
go [] = Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
go (TVar Status
tv : [TVar Status]
tvs) = do
Bool
b <- STM Bool -> IO Bool
forall a. STM a -> IO a
atomically (STM Bool -> IO Bool) -> STM Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
tv STM Status -> (Status -> STM Bool) -> STM Bool
forall a b. STM a -> (a -> STM b) -> STM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Status
s -> case Status
s of Done Result
r -> Bool -> STM Bool
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Result -> Bool
resultSuccessful Result
r); Status
_ -> STM Bool
forall a. STM a
retry
if Bool
b then [TVar Status] -> IO Bool
go [TVar Status]
tvs else Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
svgCollect :: IORef [(TestName, Estimate)] -> IntMap (TestName, TVar Status) -> IO ()
svgCollect :: IORef [(String, Estimate)] -> IntMap (String, TVar Status) -> IO ()
svgCollect IORef [(String, Estimate)]
ref = ((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status) -> IO ())
-> ((String, TVar Status) -> IO ())
-> IntMap (String, TVar Status)
-> IO ()
forall a b. (a -> b) -> a -> b
$ \(String
name, TVar Status
tv) -> do
Result
r <- STM Result -> IO Result
forall a. STM a -> IO a
atomically (STM Result -> IO Result) -> STM Result -> IO Result
forall a b. (a -> b) -> a -> b
$ TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
tv STM Status -> (Status -> STM Result) -> STM Result
forall a b. STM a -> (a -> STM b) -> STM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Status
s -> case Status
s of Done Result
r -> Result -> STM Result
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Result
r; Status
_ -> STM Result
forall a. STM a
retry
case String -> Maybe (WithLoHi Estimate)
forall a. Read a => String -> Maybe a
safeRead (Result -> String
resultDescription Result
r) of
Maybe (WithLoHi Estimate)
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just (WithLoHi Estimate
est Double
_ Double
_) -> IORef [(String, Estimate)]
-> ([(String, Estimate)] -> [(String, Estimate)]) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef [(String, Estimate)]
ref ((String
name, Estimate
est) (String, Estimate) -> [(String, Estimate)] -> [(String, Estimate)]
forall a. a -> [a] -> [a]
:)
svgRender :: [(TestName, Estimate)] -> String
svgRender :: [(String, Estimate)] -> String
svgRender [] = String
""
svgRender [(String, Estimate)]
pairs = String
header String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ((Word64 -> (String, Estimate) -> String)
-> [Word64] -> [(String, Estimate)] -> [String]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
(\Word64
i (String
name, Estimate
est) -> Word64 -> Word64 -> Double -> String -> Estimate -> String
svgRenderItem Word64
i Word64
l Double
xMax (ShowS
forall a. [a] -> [a]
dropAllPrefix String
name) Estimate
est)
[Word64
0..]
[(String, Estimate)]
pairs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
footer
where
dropAllPrefix :: [a] -> [a]
dropAllPrefix
| ((String, Estimate) -> Bool) -> [(String, Estimate)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((String
"All." String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) (String -> Bool)
-> ((String, Estimate) -> String) -> (String, Estimate) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, Estimate) -> String
forall a b. (a, b) -> a
fst) [(String, Estimate)]
pairs = Key -> [a] -> [a]
forall a. Key -> [a] -> [a]
drop Key
4
| Bool
otherwise = [a] -> [a]
forall a. a -> a
id
l :: Word64
l = [(String, Estimate)] -> Word64
forall i a. Num i => [a] -> i
genericLength [(String, Estimate)]
pairs
findMaxX :: Estimate -> Word64
findMaxX (Estimate Measurement
m Word64
stdev) = Measurement -> Word64
measTime Measurement
m Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev
xMax :: Double
xMax = Word64 -> Double
word64ToDouble (Word64 -> Double) -> Word64 -> Double
forall a b. (a -> b) -> a -> b
$ [Word64] -> Word64
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Word64] -> Word64) -> [Word64] -> Word64
forall a b. (a -> b) -> a -> b
$ Word64
forall a. Bounded a => a
minBound Word64 -> [Word64] -> [Word64]
forall a. a -> [a] -> [a]
: ((String, Estimate) -> Word64) -> [(String, Estimate)] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map (Estimate -> Word64
findMaxX (Estimate -> Word64)
-> ((String, Estimate) -> Estimate) -> (String, Estimate) -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, Estimate) -> Estimate
forall a b. (a, b) -> b
snd) [(String, Estimate)]
pairs
header :: String
header = String -> Word64 -> Double -> Word64 -> Double -> String
forall r. PrintfType r => String -> r
printf String
"<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"%i\" width=\"%f\" font-size=\"%i\" font-family=\"sans-serif\" stroke-width=\"2\">\n<g transform=\"translate(%f 0)\">\n" (Word64 -> Word64
svgItemOffset Word64
l Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
15) Double
svgCanvasWidth Word64
svgFontSize Double
svgCanvasMargin
footer :: String
footer = String
"</g>\n</svg>\n"
svgCanvasWidth :: Double
svgCanvasWidth :: Double
svgCanvasWidth = Double
960
svgCanvasMargin :: Double
svgCanvasMargin :: Double
svgCanvasMargin = Double
10
svgItemOffset :: Word64 -> Word64
svgItemOffset :: Word64 -> Word64
svgItemOffset Word64
i = Word64
22 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
55 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
i
svgFontSize :: Word64
svgFontSize :: Word64
svgFontSize = Word64
16
svgRenderItem :: Word64 -> Word64 -> Double -> TestName -> Estimate -> String
svgRenderItem :: Word64 -> Word64 -> Double -> String -> Estimate -> String
svgRenderItem Word64
i Word64
iMax Double
xMax String
name est :: Estimate
est@(Estimate Measurement
m Word64
stdev) =
(if String -> Double
forall i a. Num i => [a] -> i
genericLength String
shortTextContent Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
glyphWidth Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
boxWidth then String
longText else String
shortText) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
box
where
y :: Word64
y = Word64 -> Word64
svgItemOffset Word64
i
y' :: Word64
y' = Word64
y Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ (Word64
svgFontSize Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
3) Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` Word64
8
y1 :: Word64
y1 = Word64
y' Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
whiskerMargin
y2 :: Word64
y2 = Word64
y' Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
boxHeight Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` Word64
2
y3 :: Word64
y3 = Word64
y' Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
boxHeight Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
whiskerMargin
x1 :: Double
x1 = Double
boxWidth Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
whiskerWidth
x2 :: Double
x2 = Double
boxWidth Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
whiskerWidth
deg :: Word64
deg = (Word64
i Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
360) Word64 -> Word64 -> Word64
forall {a}. Integral a => a -> a -> a
`quot` Word64
iMax
glyphWidth :: Double
glyphWidth = Word64 -> Double
word64ToDouble Word64
svgFontSize Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
scale :: Word64 -> Double
scale Word64
w = Word64 -> Double
word64ToDouble Word64
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
svgCanvasWidth Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
svgCanvasMargin) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
xMax
boxWidth :: Double
boxWidth = Word64 -> Double
scale (Measurement -> Word64
measTime Measurement
m)
whiskerWidth :: Double
whiskerWidth = Word64 -> Double
scale (Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
stdev)
boxHeight :: Word64
boxHeight = Word64
22
whiskerMargin :: Word64
whiskerMargin = Word64
5
box :: String
box = String
-> String
-> Word64
-> Word64
-> Double
-> Word64
-> Word64
-> Word64
-> Double
-> Double
-> Word64
-> Word64
-> Double
-> Double
-> Word64
-> Word64
-> Double
-> Double
-> Word64
-> Word64
-> String
forall r. PrintfType r => String -> r
printf String
boxTemplate
(Estimate -> String
prettyEstimate Estimate
est)
Word64
y' Word64
boxHeight Double
boxWidth Word64
deg Word64
deg
Word64
deg
Double
x1 Double
x2 Word64
y2 Word64
y2
Double
x1 Double
x1 Word64
y1 Word64
y3
Double
x2 Double
x2 Word64
y1 Word64
y3
boxTemplate :: String
boxTemplate
= String
"<g>\n<title>%s</title>\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<rect y=\"%i\" rx=\"5\" height=\"%i\" width=\"%f\" fill=\"hsl(%i, 100%%, 80%%)\" stroke=\"hsl(%i, 100%%, 55%%)\" />\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<g stroke=\"hsl(%i, 100%%, 40%%)\">"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<line x1=\"%f\" x2=\"%f\" y1=\"%i\" y2=\"%i\" />\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<line x1=\"%f\" x2=\"%f\" y1=\"%i\" y2=\"%i\" />\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<line x1=\"%f\" x2=\"%f\" y1=\"%i\" y2=\"%i\" />\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"</g>\n</g>\n"
longText :: String
longText = String -> Word64 -> Word64 -> String -> Word64 -> Double -> ShowS
forall r. PrintfType r => String -> r
printf String
longTextTemplate
Word64
deg
Word64
y (ShowS
encodeSvg String
name)
Word64
y Double
boxWidth (Word64 -> String
showPicos4 (Measurement -> Word64
measTime Measurement
m))
longTextTemplate :: String
longTextTemplate
= String
"<g fill=\"hsl(%i, 100%%, 40%%)\">\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<text y=\"%i\">%s</text>\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"<text y=\"%i\" x=\"%f\" text-anchor=\"end\">%s</text>\n"
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"</g>\n"
shortTextContent :: String
shortTextContent = ShowS
encodeSvg String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
showPicos4 (Measurement -> Word64
measTime Measurement
m)
shortText :: String
shortText = String -> Word64 -> Word64 -> ShowS
forall r. PrintfType r => String -> r
printf String
shortTextTemplate Word64
deg Word64
y String
shortTextContent
shortTextTemplate :: String
shortTextTemplate = String
"<text fill=\"hsl(%i, 100%%, 40%%)\" y=\"%i\">%s</text>\n"
encodeSvg :: String -> String
encodeSvg :: ShowS
encodeSvg [] = []
encodeSvg (Char
'<' : String
xs) = Char
'&' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
'l' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
't' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
';' Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
encodeSvg String
xs
encodeSvg (Char
'&' : String
xs) = Char
'&' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
'a' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
'm' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
'p' Char -> ShowS
forall a. a -> [a] -> [a]
: Char
';' Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
encodeSvg String
xs
encodeSvg (Char
x : String
xs) = Char
x Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
encodeSvg String
xs
newtype BaselinePath = BaselinePath FilePath
deriving
( BaselinePath -> BaselinePath -> Bool
(BaselinePath -> BaselinePath -> Bool)
-> (BaselinePath -> BaselinePath -> Bool) -> Eq BaselinePath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BaselinePath -> BaselinePath -> Bool
== :: BaselinePath -> BaselinePath -> Bool
$c/= :: BaselinePath -> BaselinePath -> Bool
/= :: BaselinePath -> BaselinePath -> Bool
Eq
, Eq BaselinePath
Eq BaselinePath =>
(BaselinePath -> BaselinePath -> Ordering)
-> (BaselinePath -> BaselinePath -> Bool)
-> (BaselinePath -> BaselinePath -> Bool)
-> (BaselinePath -> BaselinePath -> Bool)
-> (BaselinePath -> BaselinePath -> Bool)
-> (BaselinePath -> BaselinePath -> BaselinePath)
-> (BaselinePath -> BaselinePath -> BaselinePath)
-> Ord BaselinePath
BaselinePath -> BaselinePath -> Bool
BaselinePath -> BaselinePath -> Ordering
BaselinePath -> BaselinePath -> BaselinePath
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: BaselinePath -> BaselinePath -> Ordering
compare :: BaselinePath -> BaselinePath -> Ordering
$c< :: BaselinePath -> BaselinePath -> Bool
< :: BaselinePath -> BaselinePath -> Bool
$c<= :: BaselinePath -> BaselinePath -> Bool
<= :: BaselinePath -> BaselinePath -> Bool
$c> :: BaselinePath -> BaselinePath -> Bool
> :: BaselinePath -> BaselinePath -> Bool
$c>= :: BaselinePath -> BaselinePath -> Bool
>= :: BaselinePath -> BaselinePath -> Bool
$cmax :: BaselinePath -> BaselinePath -> BaselinePath
max :: BaselinePath -> BaselinePath -> BaselinePath
$cmin :: BaselinePath -> BaselinePath -> BaselinePath
min :: BaselinePath -> BaselinePath -> BaselinePath
Ord
)
instance IsOption (Maybe BaselinePath) where
defaultValue :: Maybe BaselinePath
defaultValue = Maybe BaselinePath
forall a. Maybe a
Nothing
parseValue :: String -> Maybe (Maybe BaselinePath)
parseValue = Maybe BaselinePath -> Maybe (Maybe BaselinePath)
forall a. a -> Maybe a
Just (Maybe BaselinePath -> Maybe (Maybe BaselinePath))
-> (String -> Maybe BaselinePath)
-> String
-> Maybe (Maybe BaselinePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BaselinePath -> Maybe BaselinePath
forall a. a -> Maybe a
Just (BaselinePath -> Maybe BaselinePath)
-> (String -> BaselinePath) -> String -> Maybe BaselinePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> BaselinePath
BaselinePath
optionName :: Tagged (Maybe BaselinePath) String
optionName = String -> Tagged (Maybe BaselinePath) String
forall a. a -> Tagged (Maybe BaselinePath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"baseline"
optionHelp :: Tagged (Maybe BaselinePath) String
optionHelp = String -> Tagged (Maybe BaselinePath) String
forall a. a -> Tagged (Maybe BaselinePath) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"File with baseline results in CSV format to compare against"
consoleBenchReporter :: Ingredient
consoleBenchReporter :: Ingredient
consoleBenchReporter = [OptionDescription]
-> (OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result))
-> Ingredient
modifyConsoleReporter [Proxy (Maybe BaselinePath) -> OptionDescription
forall v. IsOption v => Proxy v -> OptionDescription
Option (Proxy (Maybe BaselinePath)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (Maybe BaselinePath))] ((OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result))
-> Ingredient)
-> (OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result))
-> Ingredient
forall a b. (a -> b) -> a -> b
$ \OptionSet
opts -> do
Set String
baseline <- case OptionSet -> Maybe BaselinePath
forall v. IsOption v => OptionSet -> v
lookupOption OptionSet
opts of
Maybe BaselinePath
Nothing -> Set String -> IO (Set String)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Set String
forall a. Set a
S.empty
Just (BaselinePath String
path) -> [String] -> Set String
forall a. Ord a => [a] -> Set a
S.fromList ([String] -> Set String)
-> (String -> [String]) -> String -> Set String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
joinQuotedFields ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> Set String) -> IO String -> IO (Set String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO String
readFile String
path IO String -> (String -> IO String) -> IO String
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> IO String
forall a. a -> IO a
evaluate (String -> IO String) -> ShowS -> String -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. NFData a => a -> a
force)
let pretty :: Estimate -> String
pretty = if Bool
hasGCStats then Estimate -> String
prettyEstimateWithGC else Estimate -> String
prettyEstimate
(String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result))
-> (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result)
forall a b. (a -> b) -> a -> b
$ \String
name Maybe (WithLoHi Result)
mDepR Result
r -> case String -> Maybe (WithLoHi Estimate)
forall a. Read a => String -> Maybe a
safeRead (Result -> String
resultDescription Result
r) of
Maybe (WithLoHi Estimate)
Nothing -> Result
r
Just (WithLoHi Estimate
est Double
lowerBound Double
upperBound) ->
(if Bool
isAcceptable then Result -> Result
forall a. a -> a
id else Result -> Result
forceFail)
Result
r { resultDescription = pretty est ++ bcompareMsg ++ formatSlowDown mSlowDown }
where
isAcceptable :: Bool
isAcceptable = Bool
isAcceptableVsBaseline Bool -> Bool -> Bool
&& Bool
isAcceptableVsBcompare
mSlowDown :: Maybe Double
mSlowDown = Set String -> String -> Estimate -> Maybe Double
compareVsBaseline Set String
baseline String
name Estimate
est
slowDown :: Double
slowDown = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
1 Maybe Double
mSlowDown
isAcceptableVsBaseline :: Bool
isAcceptableVsBaseline = Double
slowDown Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
lowerBound Bool -> Bool -> Bool
&& Double
slowDown Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
upperBound
(Bool
isAcceptableVsBcompare, String
bcompareMsg) = case Maybe (WithLoHi Result)
mDepR of
Maybe (WithLoHi Result)
Nothing -> (Bool
True, String
"")
Just (WithLoHi Result
depR Double
depLowerBound Double
depUpperBound) -> case String -> Maybe (WithLoHi Estimate)
forall a. Read a => String -> Maybe a
safeRead (Result -> String
resultDescription Result
depR) of
Maybe (WithLoHi Estimate)
Nothing -> (Bool
True, String
"")
Just (WithLoHi Estimate
depEst Double
_ Double
_) -> let ratio :: Double
ratio = Estimate -> Double
estTime Estimate
est Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Estimate -> Double
estTime Estimate
depEst in
( Double
ratio Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
depLowerBound Bool -> Bool -> Bool
&& Double
ratio Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
depUpperBound
, String -> Double -> String
forall r. PrintfType r => String -> r
printf String
", %.2fx" Double
ratio
)
joinQuotedFields :: [String] -> [String]
joinQuotedFields :: [String] -> [String]
joinQuotedFields [] = []
joinQuotedFields (String
x : [String]
xs)
| String -> Bool
areQuotesBalanced String
x = String
x String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
joinQuotedFields [String]
xs
| Bool
otherwise = case (String -> Bool) -> [String] -> ([String], [String])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span String -> Bool
areQuotesBalanced [String]
xs of
([String]
_, []) -> []
([String]
ys, String
z : [String]
zs) -> [String] -> String
unlines (String
x String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
ys [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
z]) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
joinQuotedFields [String]
zs
where
areQuotesBalanced :: String -> Bool
areQuotesBalanced = Key -> Bool
forall a. Integral a => a -> Bool
even (Key -> Bool) -> (String -> Key) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Key
forall a. [a] -> Key
forall (t :: * -> *) a. Foldable t => t a -> Key
length (String -> Key) -> ShowS -> String -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'"')
estTime :: Estimate -> Double
estTime :: Estimate -> Double
estTime = Word64 -> Double
word64ToDouble (Word64 -> Double) -> (Estimate -> Word64) -> Estimate -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Measurement -> Word64
measTime (Measurement -> Word64)
-> (Estimate -> Measurement) -> Estimate -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Estimate -> Measurement
estMean
compareVsBaseline :: S.Set String -> TestName -> Estimate -> Maybe Double
compareVsBaseline :: Set String -> String -> Estimate -> Maybe Double
compareVsBaseline Set String
baseline String
name (Estimate Measurement
m Word64
stdev) = case Maybe (Int64, Int64)
mOld of
Maybe (Int64, Int64)
Nothing -> Maybe Double
forall a. Maybe a
Nothing
Just (Int64
oldTime, Int64
oldDoubleSigma)
| Int64 -> Int64
forall {a}. Num a => a -> a
abs (Int64
time Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
oldTime) Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64 -> Int64 -> Int64
forall a. Ord a => a -> a -> a
max (Int64
2 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Word64 -> Int64
word64ToInt64 Word64
stdev) Int64
oldDoubleSigma -> Double -> Maybe Double
forall a. a -> Maybe a
Just Double
1
| Bool
otherwise -> Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double) -> Double -> Maybe Double
forall a b. (a -> b) -> a -> b
$ Int64 -> Double
int64ToDouble Int64
time Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int64 -> Double
int64ToDouble Int64
oldTime
where
time :: Int64
time = Word64 -> Int64
word64ToInt64 (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ Measurement -> Word64
measTime Measurement
m
mOld :: Maybe (Int64, Int64)
mOld :: Maybe (Int64, Int64)
mOld = do
let prefix :: String
prefix = ShowS
encodeCsv String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
","
(String
line, Set String
furtherLines) <- Set String -> Maybe (String, Set String)
forall a. Set a -> Maybe (a, Set a)
S.minView (Set String -> Maybe (String, Set String))
-> Set String -> Maybe (String, Set String)
forall a b. (a -> b) -> a -> b
$ (Set String, Set String) -> Set String
forall a b. (a, b) -> b
snd ((Set String, Set String) -> Set String)
-> (Set String, Set String) -> Set String
forall a b. (a -> b) -> a -> b
$ String -> Set String -> (Set String, Set String)
forall a. Ord a => a -> Set a -> (Set a, Set a)
S.split String
prefix Set String
baseline
case Set String -> Maybe (String, Set String)
forall a. Set a -> Maybe (a, Set a)
S.minView Set String
furtherLines of
Maybe (String, Set String)
Nothing -> () -> Maybe ()
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just (String
nextLine, Set String
_) -> case String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
prefix String
nextLine of
Maybe String
Nothing -> () -> Maybe ()
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just{} -> Maybe ()
forall a. Maybe a
Nothing
(String
timeCell, Char
',' : String
rest) <- (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
',') (String -> (String, String))
-> Maybe String -> Maybe (String, String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
prefix String
line
let doubleSigmaCell :: String
doubleSigmaCell = (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
',') String
rest
(,) (Int64 -> Int64 -> (Int64, Int64))
-> Maybe Int64 -> Maybe (Int64 -> (Int64, Int64))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe Int64
forall a. Read a => String -> Maybe a
safeRead String
timeCell Maybe (Int64 -> (Int64, Int64))
-> Maybe Int64 -> Maybe (Int64, Int64)
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> Maybe Int64
forall a. Read a => String -> Maybe a
safeRead String
doubleSigmaCell
formatSlowDown :: Maybe Double -> String
formatSlowDown :: Maybe Double -> String
formatSlowDown Maybe Double
Nothing = String
""
formatSlowDown (Just Double
ratio) = case Int64
percents Int64 -> Int64 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Int64
0 of
Ordering
LT -> String -> Int64 -> String
forall r. PrintfType r => String -> r
printf String
", %2i%% less than baseline" (-Int64
percents)
Ordering
EQ -> String
", same as baseline"
Ordering
GT -> String -> Int64 -> String
forall r. PrintfType r => String -> r
printf String
", %2i%% more than baseline" Int64
percents
where
percents :: Int64
percents :: Int64
percents = Double -> Int64
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate ((Double
ratio Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100)
forceFail :: Result -> Result
forceFail :: Result -> Result
forceFail Result
r = Result
r { resultOutcome = Failure TestFailed, resultShortDescription = "FAIL" }
data Unique a = None | Unique !a | NotUnique
deriving ((forall a b. (a -> b) -> Unique a -> Unique b)
-> (forall a b. a -> Unique b -> Unique a) -> Functor Unique
forall a b. a -> Unique b -> Unique a
forall a b. (a -> b) -> Unique a -> Unique b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Unique a -> Unique b
fmap :: forall a b. (a -> b) -> Unique a -> Unique b
$c<$ :: forall a b. a -> Unique b -> Unique a
<$ :: forall a b. a -> Unique b -> Unique a
Functor)
instance Semigroup (Unique a) where
Unique a
None <> :: Unique a -> Unique a -> Unique a
<> Unique a
a = Unique a
a
Unique a
a <> Unique a
None = Unique a
a
Unique a
_ <> Unique a
_ = Unique a
forall a. Unique a
NotUnique
instance Monoid (Unique a) where
mempty :: Unique a
mempty = Unique a
forall a. Unique a
None
mappend :: Unique a -> Unique a -> Unique a
mappend = Unique a -> Unique a -> Unique a
forall a. Semigroup a => a -> a -> a
(<>)
modifyConsoleReporter
:: [OptionDescription]
-> (OptionSet -> IO (TestName -> Maybe (WithLoHi Result) -> Result -> Result))
-> Ingredient
modifyConsoleReporter :: [OptionDescription]
-> (OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result))
-> Ingredient
modifyConsoleReporter [OptionDescription]
desc' OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result)
iof = [OptionDescription]
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
TestReporter ([OptionDescription]
desc [OptionDescription] -> [OptionDescription] -> [OptionDescription]
forall a. [a] -> [a] -> [a]
++ [OptionDescription]
desc') ((OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient)
-> (OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
-> Ingredient
forall a b. (a -> b) -> a -> b
$ \OptionSet
opts Benchmark
tree ->
let nameSeqs :: IntMap (Seq String)
nameSeqs = [(Key, Seq String)] -> IntMap (Seq String)
forall a. [(Key, a)] -> IntMap a
IM.fromDistinctAscList ([(Key, Seq String)] -> IntMap (Seq String))
-> [(Key, Seq String)] -> IntMap (Seq String)
forall a b. (a -> b) -> a -> b
$ [Key] -> [Seq String] -> [(Key, Seq String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Key
0..] ([Seq String] -> [(Key, Seq String)])
-> [Seq String] -> [(Key, Seq String)]
forall a b. (a -> b) -> a -> b
$ OptionSet -> Benchmark -> [Seq String]
testNameSeqs OptionSet
opts Benchmark
tree
namesAndDeps :: IntMap (String, Maybe (WithLoHi Key))
namesAndDeps = [(Key, (String, Maybe (WithLoHi Key)))]
-> IntMap (String, Maybe (WithLoHi Key))
forall a. [(Key, a)] -> IntMap a
IM.fromDistinctAscList ([(Key, (String, Maybe (WithLoHi Key)))]
-> IntMap (String, Maybe (WithLoHi Key)))
-> [(Key, (String, Maybe (WithLoHi Key)))]
-> IntMap (String, Maybe (WithLoHi Key))
forall a b. (a -> b) -> a -> b
$ [Key]
-> [(String, Maybe (WithLoHi Key))]
-> [(Key, (String, Maybe (WithLoHi Key)))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Key
0..] ([(String, Maybe (WithLoHi Key))]
-> [(Key, (String, Maybe (WithLoHi Key)))])
-> [(String, Maybe (WithLoHi Key))]
-> [(Key, (String, Maybe (WithLoHi Key)))]
forall a b. (a -> b) -> a -> b
$ ((String, Unique (WithLoHi Key)) -> (String, Maybe (WithLoHi Key)))
-> [(String, Unique (WithLoHi Key))]
-> [(String, Maybe (WithLoHi Key))]
forall a b. (a -> b) -> [a] -> [b]
map ((Unique (WithLoHi Key) -> Maybe (WithLoHi Key))
-> (String, Unique (WithLoHi Key))
-> (String, Maybe (WithLoHi Key))
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second Unique (WithLoHi Key) -> Maybe (WithLoHi Key)
forall {a}. Unique a -> Maybe a
isSingle)
([(String, Unique (WithLoHi Key))]
-> [(String, Maybe (WithLoHi Key))])
-> [(String, Unique (WithLoHi Key))]
-> [(String, Maybe (WithLoHi Key))]
forall a b. (a -> b) -> a -> b
$ IntMap (Seq String)
-> OptionSet -> Benchmark -> [(String, Unique (WithLoHi Key))]
testNamesAndDeps IntMap (Seq String)
nameSeqs OptionSet
opts Benchmark
tree
modifySMap :: StatusMap -> IO StatusMap
modifySMap = (OptionSet
-> IO (String -> Maybe (WithLoHi Result) -> Result -> Result)
iof OptionSet
opts IO (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> ((String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap)
-> IO StatusMap
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=) (((String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap)
-> IO StatusMap)
-> (StatusMap
-> (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap)
-> StatusMap
-> IO StatusMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> IO StatusMap)
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap
forall a b c. (a -> b -> c) -> b -> a -> c
flip (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> IO StatusMap
postprocessResult
(IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap)
-> (StatusMap
-> IntMap (String, Maybe (WithLoHi Key), TVar Status))
-> StatusMap
-> (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IO StatusMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, Maybe (WithLoHi Key))
-> TVar Status -> (String, Maybe (WithLoHi Key), TVar Status))
-> IntMap (String, Maybe (WithLoHi Key))
-> StatusMap
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
forall a b c. (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c
IM.intersectionWith (\(String
a, Maybe (WithLoHi Key)
b) TVar Status
c -> (String
a, Maybe (WithLoHi Key)
b, TVar Status
c)) IntMap (String, Maybe (WithLoHi Key))
namesAndDeps
in (StatusMap -> IO StatusMap
modifySMap (StatusMap -> IO StatusMap)
-> (StatusMap -> IO (Double -> IO Bool))
-> StatusMap
-> IO (Double -> IO Bool)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=>) ((StatusMap -> IO (Double -> IO Bool))
-> StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
-> Maybe (StatusMap -> IO (Double -> IO Bool))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool))
cb OptionSet
opts Benchmark
tree
where
([OptionDescription]
desc, OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool))
cb) = case Ingredient
consoleTestReporter of
TestReporter [OptionDescription]
d OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool))
c -> ([OptionDescription]
d, OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool))
c)
Ingredient
_ -> String
-> ([OptionDescription],
OptionSet
-> Benchmark -> Maybe (StatusMap -> IO (Double -> IO Bool)))
forall a. HasCallStack => String -> a
error String
"modifyConsoleReporter: consoleTestReporter must be TestReporter"
isSingle :: Unique a -> Maybe a
isSingle (Unique a
a) = a -> Maybe a
forall a. a -> Maybe a
Just a
a
isSingle Unique a
_ = Maybe a
forall a. Maybe a
Nothing
testNameSeqs :: OptionSet -> TestTree -> [Seq TestName]
testNameSeqs :: OptionSet -> Benchmark -> [Seq String]
testNameSeqs = TreeFold [Seq String] -> OptionSet -> Benchmark -> [Seq String]
forall b. Monoid b => TreeFold b -> OptionSet -> Benchmark -> b
foldTestTree TreeFold [Seq String]
forall b. Monoid b => TreeFold b
trivialFold
{ foldSingle = const $ const . (:[]) . Seq.singleton
#if MIN_VERSION_tasty(1,5,0)
, foldGroup = const $ (. concat) . map . (<|)
#else
, foldGroup = const $ map . (<|)
#endif
}
testNamesAndDeps :: IntMap (Seq TestName) -> OptionSet -> TestTree -> [(TestName, Unique (WithLoHi IM.Key))]
testNamesAndDeps :: IntMap (Seq String)
-> OptionSet -> Benchmark -> [(String, Unique (WithLoHi Key))]
testNamesAndDeps IntMap (Seq String)
im = TreeFold [(String, Unique (WithLoHi Key))]
-> OptionSet -> Benchmark -> [(String, Unique (WithLoHi Key))]
forall b. Monoid b => TreeFold b -> OptionSet -> Benchmark -> b
foldTestTree TreeFold [(String, Unique (WithLoHi Key))]
forall b. Monoid b => TreeFold b
trivialFold
{ foldSingle = const $ const . (: []) . (, mempty)
#if MIN_VERSION_tasty(1,5,0)
, foldGroup = const $ (. concat) . map . first . (++) . (++ ".")
#else
, foldGroup = const $ map . first . (++) . (++ ".")
#endif
, foldAfter = const foldDeps
}
where
foldDeps :: DependencyType -> Expr -> [(a, Unique (WithLoHi IM.Key))] -> [(a, Unique (WithLoHi IM.Key))]
foldDeps :: forall a.
DependencyType
-> Expr
-> [(a, Unique (WithLoHi Key))]
-> [(a, Unique (WithLoHi Key))]
foldDeps DependencyType
AllSucceed (And (StringLit String
xs) Expr
p)
| String
bcomparePrefix String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
xs
, Just (Double
lo :: Double, Double
hi :: Double) <- String -> Maybe (Double, Double)
forall a. Read a => String -> Maybe a
safeRead (String -> Maybe (Double, Double))
-> String -> Maybe (Double, Double)
forall a b. (a -> b) -> a -> b
$ Key -> ShowS
forall a. Key -> [a] -> [a]
drop (String -> Key
forall a. [a] -> Key
forall (t :: * -> *) a. Foldable t => t a -> Key
length String
bcomparePrefix) String
xs
= ((a, Unique (WithLoHi Key)) -> (a, Unique (WithLoHi Key)))
-> [(a, Unique (WithLoHi Key))] -> [(a, Unique (WithLoHi Key))]
forall a b. (a -> b) -> [a] -> [b]
map (((a, Unique (WithLoHi Key)) -> (a, Unique (WithLoHi Key)))
-> [(a, Unique (WithLoHi Key))] -> [(a, Unique (WithLoHi Key))])
-> ((a, Unique (WithLoHi Key)) -> (a, Unique (WithLoHi Key)))
-> [(a, Unique (WithLoHi Key))]
-> [(a, Unique (WithLoHi Key))]
forall a b. (a -> b) -> a -> b
$ (Unique (WithLoHi Key) -> Unique (WithLoHi Key))
-> (a, Unique (WithLoHi Key)) -> (a, Unique (WithLoHi Key))
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second ((Unique (WithLoHi Key) -> Unique (WithLoHi Key))
-> (a, Unique (WithLoHi Key)) -> (a, Unique (WithLoHi Key)))
-> (Unique (WithLoHi Key) -> Unique (WithLoHi Key))
-> (a, Unique (WithLoHi Key))
-> (a, Unique (WithLoHi Key))
forall a b. (a -> b) -> a -> b
$ Unique (WithLoHi Key)
-> Unique (WithLoHi Key) -> Unique (WithLoHi Key)
forall a. Monoid a => a -> a -> a
mappend (Unique (WithLoHi Key)
-> Unique (WithLoHi Key) -> Unique (WithLoHi Key))
-> Unique (WithLoHi Key)
-> Unique (WithLoHi Key)
-> Unique (WithLoHi Key)
forall a b. (a -> b) -> a -> b
$ (\Key
x -> Key -> Double -> Double -> WithLoHi Key
forall a. a -> Double -> Double -> WithLoHi a
WithLoHi Key
x Double
lo Double
hi) (Key -> WithLoHi Key) -> Unique Key -> Unique (WithLoHi Key)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IntMap (Seq String) -> Expr -> Unique Key
findMatchingKeys IntMap (Seq String)
im Expr
p
foldDeps DependencyType
_ Expr
_ = [(a, Unique (WithLoHi Key))] -> [(a, Unique (WithLoHi Key))]
forall a. a -> a
id
findMatchingKeys :: IntMap (Seq TestName) -> Expr -> Unique IM.Key
findMatchingKeys :: IntMap (Seq String) -> Expr -> Unique Key
findMatchingKeys IntMap (Seq String)
im Expr
pattern =
((Key, Seq String) -> Unique Key)
-> [(Key, Seq String)] -> Unique Key
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\(Key
k, Seq String
v) -> if Seq String -> M Bool -> Either String Bool
forall a. Seq String -> M a -> Either String a
withFields Seq String
v M Bool
pat Either String Bool -> Either String Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
True then Key -> Unique Key
forall a. a -> Unique a
Unique Key
k else Unique Key
forall a. Monoid a => a
mempty) ([(Key, Seq String)] -> Unique Key)
-> [(Key, Seq String)] -> Unique Key
forall a b. (a -> b) -> a -> b
$ IntMap (Seq String) -> [(Key, Seq String)]
forall a. IntMap a -> [(Key, a)]
IM.assocs IntMap (Seq String)
im
where
pat :: M Bool
pat = Expr -> M Value
eval Expr
pattern M Value -> (Value -> M Bool) -> M Bool
forall a b.
ReaderT (Seq String) (Either String) a
-> (a -> ReaderT (Seq String) (Either String) b)
-> ReaderT (Seq String) (Either String) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> M Bool
asB
postprocessResult
:: (TestName -> Maybe (WithLoHi Result) -> Result -> Result)
-> IntMap (TestName, Maybe (WithLoHi IM.Key), TVar Status)
-> IO StatusMap
postprocessResult :: (String -> Maybe (WithLoHi Result) -> Result -> Result)
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> IO StatusMap
postprocessResult String -> Maybe (WithLoHi Result) -> Result -> Result
f IntMap (String, Maybe (WithLoHi Key), TVar Status)
src = do
IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
paired <- IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> ((String, Maybe (WithLoHi Key), TVar Status)
-> IO (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
-> IO
(IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM IntMap (String, Maybe (WithLoHi Key), TVar Status)
src (((String, Maybe (WithLoHi Key), TVar Status)
-> IO (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
-> IO
(IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)))
-> ((String, Maybe (WithLoHi Key), TVar Status)
-> IO (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
-> IO
(IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
forall a b. (a -> b) -> a -> b
$ \(String
name, Maybe (WithLoHi Key)
mDepId, TVar Status
tv) -> (String
name, Maybe (WithLoHi Key)
mDepId, TVar Status
tv,) (TVar Status
-> (String, Maybe (WithLoHi Key), TVar Status, TVar Status))
-> IO (TVar Status)
-> IO (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Status -> IO (TVar Status)
forall a. a -> IO (TVar a)
newTVarIO Status
NotStarted
let doUpdate :: IO Bool
doUpdate = STM Bool -> IO Bool
forall a. STM a -> IO a
atomically (STM Bool -> IO Bool) -> STM Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ do
(Any Bool
anyUpdated, All Bool
allDone) <-
Ap STM (Any, All) -> STM (Any, All)
forall (f :: * -> *) a. Ap f a -> f a
getApp (Ap STM (Any, All) -> STM (Any, All))
-> Ap STM (Any, All) -> STM (Any, All)
forall a b. (a -> b) -> a -> b
$ (((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> ((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> Ap STM (Any, All)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All)
forall m a. Monoid m => (a -> m) -> IntMap a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
paired (((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> Ap STM (Any, All))
-> ((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> Ap STM (Any, All))
-> Ap STM (Any, All)
forall a b. (a -> b) -> a -> b
$ \(String
name, Maybe (WithLoHi Key)
mDepId, TVar Status
newTV, TVar Status
oldTV) -> STM (Any, All) -> Ap STM (Any, All)
forall (f :: * -> *) a. f a -> Ap f a
Ap (STM (Any, All) -> Ap STM (Any, All))
-> STM (Any, All) -> Ap STM (Any, All)
forall a b. (a -> b) -> a -> b
$ do
Status
old <- TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
oldTV
case Status
old of
Done{} -> (Any, All) -> STM (Any, All)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Any
Any Bool
False, Bool -> All
All Bool
True)
Status
_ -> do
Status
new <- TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
newTV
case Status
new of
Done Result
res -> do
Maybe (WithLoHi Result)
depRes <- case Maybe (WithLoHi Key)
mDepId of
Maybe (WithLoHi Key)
Nothing -> Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result))
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (WithLoHi Result)
forall a. Maybe a
Nothing
Just (WithLoHi Key
depId Double
lo Double
hi) -> case Key
-> IntMap (String, Maybe (WithLoHi Key), TVar Status)
-> Maybe (String, Maybe (WithLoHi Key), TVar Status)
forall a. Key -> IntMap a -> Maybe a
IM.lookup Key
depId IntMap (String, Maybe (WithLoHi Key), TVar Status)
src of
Maybe (String, Maybe (WithLoHi Key), TVar Status)
Nothing -> Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result))
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (WithLoHi Result)
forall a. Maybe a
Nothing
Just (String
_, Maybe (WithLoHi Key)
_, TVar Status
depTV) -> do
Status
depStatus <- TVar Status -> STM Status
forall a. TVar a -> STM a
readTVar TVar Status
depTV
case Status
depStatus of
Done Result
dep -> Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result))
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result)))
-> Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result))
forall a b. (a -> b) -> a -> b
$ WithLoHi Result -> Maybe (WithLoHi Result)
forall a. a -> Maybe a
Just (Result -> Double -> Double -> WithLoHi Result
forall a. a -> Double -> Double -> WithLoHi a
WithLoHi Result
dep Double
lo Double
hi)
Status
_ -> Maybe (WithLoHi Result) -> STM (Maybe (WithLoHi Result))
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (WithLoHi Result)
forall a. Maybe a
Nothing
TVar Status -> Status -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Status
oldTV (Result -> Status
Done (String -> Maybe (WithLoHi Result) -> Result -> Result
f String
name Maybe (WithLoHi Result)
depRes Result
res))
(Any, All) -> STM (Any, All)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Any
Any Bool
True, Bool -> All
All Bool
True)
#if MIN_VERSION_tasty(1,5,0)
Executing Progress
newProgr -> do
let updated :: Bool
updated = case Status
old of
Executing Progress
oldProgr -> Progress
oldProgr Progress -> Progress -> Bool
forall a. Eq a => a -> a -> Bool
/= Progress
newProgr
Status
_ -> Bool
True
Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
updated (STM () -> STM ()) -> STM () -> STM ()
forall a b. (a -> b) -> a -> b
$
TVar Status -> Status -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Status
oldTV (Progress -> Status
Executing Progress
newProgr)
(Any, All) -> STM (Any, All)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Any
Any Bool
updated, Bool -> All
All Bool
False)
#else
Executing{} -> pure (Any False, All False)
#endif
Status
NotStarted -> (Any, All) -> STM (Any, All)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Any
Any Bool
False, Bool -> All
All Bool
False)
if Bool
anyUpdated Bool -> Bool -> Bool
|| Bool
allDone then Bool -> STM Bool
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
allDone else STM Bool
forall a. STM a
retry
adNauseam :: IO ()
adNauseam = IO Bool
doUpdate IO Bool -> (Bool -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
`unless` IO ()
adNauseam)
ThreadId
_ <- IO () -> IO ThreadId
forkIO IO ()
adNauseam
StatusMap -> IO StatusMap
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (StatusMap -> IO StatusMap) -> StatusMap -> IO StatusMap
forall a b. (a -> b) -> a -> b
$ ((String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> TVar Status)
-> IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
-> StatusMap
forall a b. (a -> b) -> IntMap a -> IntMap b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(String
_, Maybe (WithLoHi Key)
_, TVar Status
_, TVar Status
a) -> TVar Status
a) IntMap (String, Maybe (WithLoHi Key), TVar Status, TVar Status)
paired
int64ToDouble :: Int64 -> Double
int64ToDouble :: Int64 -> Double
int64ToDouble = Int64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral
word64ToInt64 :: Word64 -> Int64
word64ToInt64 :: Word64 -> Int64
word64ToInt64 = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
#endif
word64ToDouble :: Word64 -> Double
word64ToDouble :: Word64 -> Double
word64ToDouble = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral
#if !MIN_VERSION_base(4,10,0)
int64ToWord64 :: Int64 -> Word64
int64ToWord64 = fromIntegral
#endif
#if defined(mingw32_HOST_OS)
#if defined(i386_HOST_ARCH)
#define CCONV stdcall
#else
#define CCONV ccall
#endif
foreign import CCONV unsafe "windows.h GetConsoleOutputCP" getConsoleOutputCP :: IO Word32
foreign import CCONV unsafe "windows.h SetConsoleOutputCP" setConsoleOutputCP :: Word32 -> IO ()
#endif
#ifdef MIN_VERSION_tasty
mapLeafBenchmarks :: ([String] -> Benchmark -> Benchmark) -> Benchmark -> Benchmark
mapLeafBenchmarks :: ([String] -> Benchmark -> Benchmark) -> Benchmark -> Benchmark
mapLeafBenchmarks [String] -> Benchmark -> Benchmark
processLeaf = [String] -> Benchmark -> Benchmark
go [String]
forall a. Monoid a => a
mempty
where
go :: [String] -> Benchmark -> Benchmark
go :: [String] -> Benchmark -> Benchmark
go [String]
path Benchmark
x = case Benchmark
x of
SingleTest String
name t
t -> [String] -> Benchmark -> Benchmark
processLeaf (String
name String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
path) (String -> t -> Benchmark
forall t. IsTest t => String -> t -> Benchmark
SingleTest String
name t
t)
TestGroup String
name [Benchmark]
tts -> String -> [Benchmark] -> Benchmark
TestGroup String
name ((Benchmark -> Benchmark) -> [Benchmark] -> [Benchmark]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> Benchmark -> Benchmark
go (String
name String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
path)) [Benchmark]
tts)
PlusTestOptions OptionSet -> OptionSet
g Benchmark
tt -> (OptionSet -> OptionSet) -> Benchmark -> Benchmark
PlusTestOptions OptionSet -> OptionSet
g ([String] -> Benchmark -> Benchmark
go [String]
path Benchmark
tt)
WithResource ResourceSpec a
res IO a -> Benchmark
f -> ResourceSpec a -> (IO a -> Benchmark) -> Benchmark
forall a. ResourceSpec a -> (IO a -> Benchmark) -> Benchmark
WithResource ResourceSpec a
res ([String] -> Benchmark -> Benchmark
go [String]
path (Benchmark -> Benchmark)
-> (IO a -> Benchmark) -> IO a -> Benchmark
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> Benchmark
f)
AskOptions OptionSet -> Benchmark
f -> (OptionSet -> Benchmark) -> Benchmark
AskOptions ([String] -> Benchmark -> Benchmark
go [String]
path (Benchmark -> Benchmark)
-> (OptionSet -> Benchmark) -> OptionSet -> Benchmark
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OptionSet -> Benchmark
f)
After DependencyType
dep Expr
expr Benchmark
tt -> DependencyType -> Expr -> Benchmark -> Benchmark
After DependencyType
dep Expr
expr ([String] -> Benchmark -> Benchmark
go [String]
path Benchmark
tt)
locateBenchmark :: [String] -> Expr
locateBenchmark :: [String] -> Expr
locateBenchmark [] = Key -> Expr
IntLit Key
1
locateBenchmark [String]
path
= (Expr -> Expr -> Expr) -> [Expr] -> Expr
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' Expr -> Expr -> Expr
And
([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ (Key -> String -> Expr) -> [Key] -> [String] -> [Expr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Key
i String
name -> Expr -> Expr -> Expr
Patterns.EQ (Expr -> Expr
Field (Expr -> Expr -> Expr
Sub Expr
NF (Key -> Expr
IntLit Key
i))) (String -> Expr
StringLit String
name)) [Key
0..] [String]
path
#endif