criterion 0.4.1.0 → 0.5.0.0
raw patch · 12 files changed
+91/−62 lines, 12 filesdep +mwc-randomdep +vectordep +vector-algorithmsdep −uvectordep −uvector-algorithmsdep ~parsecdep ~statisticsPVP ok
version bump matches the API change (PVP)
Dependencies added: mwc-random, vector, vector-algorithms
Dependencies removed: uvector, uvector-algorithms
Dependency ranges changed: parsec, statistics
API changes (from Hackage documentation)
+ Criterion: whnfIO :: (NFData a) => IO a -> IO ()
+ Criterion.Main: whnfIO :: (NFData a) => IO a -> IO ()
+ Criterion.Types: whnfIO :: (NFData a) => IO a -> IO ()
- Criterion.Measurement: runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO ((Double :*: Int) :*: a)
+ Criterion.Measurement: runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO (Double, Int, a)
- Criterion.Measurement: time :: IO a -> IO (Double :*: a)
+ Criterion.Measurement: time :: IO a -> IO (Double, a)
- Criterion.Plot: plotKDE :: PlotOutput -> String -> Maybe (Double :*: Double) -> Points -> UArr Double -> IO ()
+ Criterion.Plot: plotKDE :: PlotOutput -> String -> Maybe (Double, Double) -> Points -> Vector Double -> IO ()
Files
- Criterion.hs +16/−14
- Criterion/Analysis.hs +3/−3
- Criterion/Config.hs +1/−1
- Criterion/Environment.hs +11/−11
- Criterion/IO.hs +1/−1
- Criterion/Main.hs +10/−8
- Criterion/Measurement.hs +17/−6
- Criterion/Monad.hs +1/−1
- Criterion/Plot.hs +7/−6
- Criterion/Types.hs +10/−2
- LICENSE +1/−1
- criterion.cabal +13/−8
Criterion.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Criterion--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -15,8 +15,9 @@ , Benchmark , Pure , nf- , nfIO , whnf+ , nfIO+ , whnfIO , bench , bgroup , runBenchmark@@ -34,15 +35,15 @@ import Criterion.Monad (Criterion, getConfig, getConfigItem) import Criterion.Plot (plotWith, plotKDE, plotTiming) import Criterion.Types (Benchmarkable(..), Benchmark(..), Pure,- bench, bgroup, nf, nfIO, whnf)-import Data.Array.Vector ((:*:)(..), concatU, lengthU, mapU)-import Statistics.Function (createIO, minMax)+ bench, bgroup, nf, nfIO, whnf, whnfIO)+import qualified Data.Vector.Unboxed as U+import Statistics.Function (create, minMax) import Statistics.KernelDensity (epanechnikovPDF)-import Statistics.RandomVariate (withSystemRandom)-import Statistics.Resampling (resample)+import Statistics.Resampling (Resample, resample) import Statistics.Resampling.Bootstrap (Estimate(..), bootstrapBCA) import Statistics.Sample (mean, stdDev) import Statistics.Types (Sample)+import System.Random.MWC (withSystemRandom) import System.Mem (performGC) import Text.Printf (printf) @@ -52,8 +53,7 @@ runBenchmark env b = do liftIO $ runForAtLeast 0.1 10000 (`replicateM_` getTime) let minTime = envClockResolution env * 1000- (testTime :*: testIters :*: _) <-- liftIO $ runForAtLeast (min minTime 0.1) 1 (run b)+ (testTime, testIters, _) <- liftIO $ runForAtLeast (min minTime 0.1) 1 (run b) prolix "ran %d iterations in %s\n" testIters (secs testTime) cfg <- getConfig let newIters = ceiling $ minTime * testItersD / testTime@@ -63,8 +63,8 @@ note "collecting %d samples, %d iterations each, in estimated %s\n" sampleCount newIters (secs (fromIntegral sampleCount * newItersD * testTime / testItersD))- times <- liftIO . fmap (mapU ((/ newItersD) . subtract (envClockCost env))) .- createIO sampleCount . const $ do+ times <- liftIO . fmap (U.map ((/ newItersD) . subtract (envClockCost env))) .+ create sampleCount . const $ do when (fromLJ cfgPerformGC cfg) $ performGC time_ (run b newIters) return times@@ -74,11 +74,12 @@ -> Criterion Sample runAndAnalyseOne env _desc b = do times <- runBenchmark env b- let numSamples = lengthU times+ let numSamples = U.length times let ests = [mean,stdDev] numResamples <- getConfigItem $ fromLJ cfgResamples note "bootstrapping with %d resamples\n" numResamples- res <- liftIO $ withSystemRandom (\gen -> resample gen ests numResamples times)+ res <- liftIO . withSystemRandom $ \gen ->+ resample gen ests numResamples times :: IO [Resample] ci <- getConfigItem $ fromLJ cfgConfInterval let [em,es] = bootstrapBCA ci times ests res (effect, v) = outlierVariance em es (fromIntegral $ numSamples)@@ -113,7 +114,8 @@ extremes = case descTimes of (_:_:_) -> toJust . minMax . concatU . map snd $ descTimes _ -> Nothing- toJust r@(lo :*: hi)+ concatU = foldr (U.++) U.empty+ toJust r@(lo, hi) | lo == infinity || hi == -infinity = Nothing | otherwise = Just r where infinity = 1/0
Criterion/Analysis.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Criterion.Analysis--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -24,7 +24,7 @@ import Criterion.IO (note) import Criterion.Measurement (secs) import Criterion.Monad (Criterion)-import Data.Array.Vector (foldlU)+import qualified Data.Vector.Unboxed as U import Data.Int (Int64) import Data.Monoid (Monoid(..)) import Statistics.Function (sort)@@ -67,7 +67,7 @@ -- | Classify outliers in a data set, using the boxplot technique. classifyOutliers :: Sample -> Outliers-classifyOutliers sa = foldlU ((. outlier) . mappend) mempty ssa+classifyOutliers sa = U.foldl ((. outlier) . mappend) mempty ssa where outlier e = Outliers { samplesSeen = 1 , lowSevere = if e <= loS then 1 else 0
Criterion/Config.hs view
@@ -2,7 +2,7 @@ -- | -- Module : Criterion.Config--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com
Criterion/Environment.hs view
@@ -2,7 +2,7 @@ -- | -- Module : Criterion.Environment--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -23,9 +23,9 @@ import Criterion.IO (note) import Criterion.Measurement (getTime, runForAtLeast, time_) import Criterion.Monad (Criterion)-import Data.Array.Vector+import qualified Data.Vector.Unboxed as U import Data.Typeable (Typeable)-import Statistics.Function (createIO)+import Statistics.Function (create) -- | Measured aspects of the execution environment. data Environment = Environment {@@ -39,7 +39,7 @@ measureEnvironment :: Criterion Environment measureEnvironment = do note "warming up\n"- (_ :*: seed :*: _) <- liftIO $ runForAtLeast 0.1 10000 resolution+ (_, seed, _) <- liftIO $ runForAtLeast 0.1 10000 resolution note "estimating clock resolution...\n" clockRes <- thd3 `fmap` liftIO (runForAtLeast 0.5 seed resolution) >>= uncurry analyseMean@@ -51,13 +51,13 @@ } where resolution k = do- times <- createIO (k+1) (const getTime)- return (tailU . filterU (>=0) . zipWithU (-) (tailU times) $ times,- lengthU times)+ times <- create (k+1) (const getTime)+ return (U.tail . U.filter (>=0) . U.zipWith (-) (U.tail times) $ times,+ U.length times) cost timeLimit = liftIO $ do let timeClock k = time_ (replicateM_ k getTime) timeClock 1- (_ :*: iters :*: elapsed) <- runForAtLeast 0.01 10000 timeClock- times <- createIO (ceiling (timeLimit / elapsed)) $ \_ -> timeClock iters- return (mapU (/ fromIntegral iters) times, lengthU times)- thd3 (_ :*: _:*: c) = c+ (_, iters, elapsed) <- runForAtLeast 0.01 10000 timeClock+ times <- create (ceiling (timeLimit / elapsed)) $ \_ -> timeClock iters+ return (U.map (/ fromIntegral iters) times, U.length times)+ thd3 (_, _, c) = c
Criterion/IO.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Criterion.IO--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com
Criterion/Main.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Criterion.Main--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -32,8 +32,9 @@ , bench , bgroup , nf- , nfIO , whnf+ , nfIO+ , whnfIO -- * Running benchmarks , defaultMain , defaultMainWith@@ -51,13 +52,14 @@ import Criterion.MultiMap (singleton) import Criterion.Monad (Criterion, withConfig) import Criterion.Types (Benchmarkable(..), Benchmark(..), Pure, bench,- benchNames, bgroup, nf, nfIO, whnf)+ benchNames, bgroup, nf, nfIO, whnf, whnfIO) import Data.List (isPrefixOf, sort) import Data.Monoid (Monoid(..), Last(..)) import System.Console.GetOpt import System.Environment (getArgs, getProgName) import System.Exit (ExitCode(..), exitWith)-import Text.ParserCombinators.Parsec+import Text.Parsec+import Text.Parsec.String -- | Parse a plot output. parsePlot :: Parser PlotOutput@@ -197,9 +199,9 @@ -- > fib n = fib (n-1) + fib (n-2) -- > -- > main = defaultMain [--- > bgroup "fib" [ bench "fib 10" $ B fib 10--- > , bench "fib 35" $ B fib 35--- > , bench "fib 37" $ B fib 37+-- > bgroup "fib" [ bench "10" $ whnf fib 10+-- > , bench "35" $ whnf fib 35+-- > , bench "37" $ whnf fib 37 -- > ] -- > ] defaultMain :: [Benchmark] -> IO ()@@ -219,7 +221,7 @@ -- > } -- > -- > main = defaultMainWith myConfig (return ()) [--- > bench "fib 30" $ B fib 30+-- > bench "fib 30" $ whnf fib 30 -- > ] -- -- If you save the above example as @\"Fib.hs\"@, you should be able
Criterion/Measurement.hs view
@@ -1,5 +1,16 @@ {-# LANGUAGE BangPatterns, ScopedTypeVariables, TypeOperators #-} +-- |+-- Module : Criterion.Measurement+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan+--+-- License : BSD-style+-- Maintainer : bos@serpentine.com+-- Stability : experimental+-- Portability : GHC+--+-- Benchmark measurement code.+ module Criterion.Measurement ( getTime@@ -10,16 +21,16 @@ ) where import Control.Monad (when)-import Data.Array.Vector ((:*:)(..)) import Data.Time.Clock.POSIX (getPOSIXTime) import Text.Printf (printf) -time :: IO a -> IO (Double :*: a)+time :: IO a -> IO (Double, a) time act = do start <- getTime result <- act end <- getTime- return (end - start :*: result)+ let !delta = end - start+ return (delta, result) time_ :: IO a -> IO Double time_ act = do@@ -31,17 +42,17 @@ getTime :: IO Double getTime = (fromRational . toRational) `fmap` getPOSIXTime -runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO (Double :*: Int :*: a)+runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO (Double, Int, a) runForAtLeast howLong initSeed act = loop initSeed (0::Int) =<< getTime where loop !seed !iters initTime = do now <- getTime when (now - initTime > howLong * 10) $ fail (printf "took too long to run: seed %d, iters %d" seed iters)- elapsed :*: result <- time (act seed)+ (elapsed,result) <- time (act seed) if elapsed < howLong then loop (seed * 2) (iters+1) initTime- else return (elapsed :*: seed :*: result)+ else return (elapsed, seed, result) secs :: Double -> String secs k
Criterion/Monad.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | -- Module : Criterion.Monad--- Copyright : (c) Neil Brown 2009+-- Copyright : (c) 2009 Neil Brown -- -- License : BSD-style -- Maintainer : bos@serpentine.com
Criterion/Plot.hs view
@@ -2,7 +2,7 @@ -- | -- Module : Criterion.Plot--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -21,11 +21,12 @@ import Control.Monad.Trans (liftIO) import Criterion.Config import Criterion.Monad (Criterion, getConfigItem)-import Data.Array.Vector+import qualified Data.Vector.Unboxed as U import Data.Char (isSpace, toLower) import Data.Foldable (forM_) import Data.List (group, intersperse) import Statistics.KernelDensity (Points, fromPoints)+import Statistics.Function (indexed) import Statistics.Types (Sample) import System.FilePath (pathSeparator) import System.IO (IOMode(..), Handle, hPutStr, withBinaryFile)@@ -53,7 +54,7 @@ plotTiming CSV desc times = do writeTo (mangle $ printf "%s timings.csv" desc) $ \h -> do putRow h ["sample", "execution time"]- forM_ (fromU $ indexedU times) $ \(x :*: y) ->+ forM_ (U.toList $ indexed times) $ \(x,y) -> putRow h [show x, show y] #ifdef HAVE_CHART@@ -80,15 +81,15 @@ -- | Plot kernel density estimate. plotKDE :: PlotOutput -- ^ The kind of output desired. -> String -- ^ Benchmark name.- -> Maybe (Double :*: Double) -- ^ Range of x-axis+ -> Maybe (Double, Double) -- ^ Range of x-axis -> Points -- ^ Points at which KDE was computed.- -> UArr Double -- ^ Kernel density estimates.+ -> U.Vector Double -- ^ Kernel density estimates. -> IO () plotKDE CSV desc _exs points pdf = do writeTo (mangle $ printf "%s densities.csv" desc) $ \h -> do putRow h ["execution time", "probability"]- forM_ (zip (fromU pdf) (fromU (fromPoints points))) $ \(x, y) ->+ forM_ (zip (U.toList pdf) (U.toList (fromPoints points))) $ \(x, y) -> putRow h [show x, show y] #ifdef HAVE_CHART
Criterion/Types.hs view
@@ -3,7 +3,7 @@ -- | -- Module : Criterion.Types--- Copyright : (c) Bryan O'Sullivan 2009+-- Copyright : (c) 2009, 2010 Bryan O'Sullivan -- -- License : BSD-style -- Maintainer : bos@serpentine.com@@ -32,6 +32,7 @@ , whnf , nf , nfIO+ , whnfIO , bench , bgroup , benchNames@@ -69,8 +70,15 @@ -- This is particularly useful for forcing a lazy IO action to be -- completely performed. nfIO :: NFData a => IO a -> IO ()-nfIO a = a >>= \k -> return $! rnf k+nfIO a = evaluate . rnf =<< a {-# INLINE nfIO #-}++-- | Perform an action, then evaluate its result to weak head normal+-- form (WHNF). This is useful for forcing an IO action whose result+-- is an expression to be evaluated down to a more useful value.+whnfIO :: NFData a => IO a -> IO ()+whnfIO a = a >>= evaluate >> return ()+{-# INLINE whnfIO #-} instance Benchmarkable Pure where run p@(WHNF _ _) = go p
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2009, Bryan O'Sullivan+Copyright (c) 2009, 2010 Bryan O'Sullivan All rights reserved. Redistribution and use in source and binary forms, with or without
criterion.cabal view
@@ -1,11 +1,11 @@ name: criterion-version: 0.4.1.0+version: 0.5.0.0 synopsis: Robust, reliable performance measurement and analysis license: BSD3 license-file: LICENSE author: Bryan O'Sullivan <bos@serpentine.com> maintainer: Bryan O'Sullivan <bos@serpentine.com>-copyright: 2009 Bryan O'Sullivan+copyright: 2009-2010 Bryan O'Sullivan category: Development, Performance, Testing build-type: Simple cabal-version: >= 1.2@@ -26,7 +26,9 @@ examples in the Criterion.Main module. flag Chart- Description: enable use of the Chart package+ description: enable use of the Chart package+ -- Broken under GHC 6.12 so far.+ default: False library exposed-modules:@@ -49,16 +51,17 @@ deepseq >= 1.1.0.0, filepath, mtl,+ mwc-random >= 0.5.0.0, parallel,- parsec,- statistics >= 0.3.5,+ parsec >= 3.1.0,+ statistics >= 0.5.1.0, time,- uvector >= 0.1.0.5,- uvector-algorithms >= 0.2+ vector >= 0.5,+ vector-algorithms >= 0.3 if flag(chart) build-depends:- Chart>=0.12,+ Chart >= 0.12, data-accessor cpp-options: -DHAVE_CHART @@ -68,3 +71,5 @@ ghc-options: -Wall -funbox-strict-fields -O2 if impl(ghc >= 6.8) ghc-options: -fwarn-tabs+ if impl(ghc >= 6.12)+ ghc-options: -fno-warn-unused-do-bind