perf 0.7.0 → 0.8.0
raw patch · 7 files changed
+101/−143 lines, 7 filesdep +mtldep −doctestdep −perfdep ~containersdep ~deepseqdep ~foldlPVP ok
version bump matches the API change (PVP)
Dependencies added: mtl
Dependencies removed: doctest, perf
Dependency ranges changed: containers, deepseq, foldl, rdtsc, text, time, transformers
API changes (from Hackage documentation)
- Perf.Measure: add :: Additive a => a -> a -> a
- Perf.Measure: class Num a => Additive a
- Perf.Measure: instance Perf.Measure.Additive Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime
- Perf.Measure: instance Perf.Measure.Additive GHC.Integer.Type.Integer
- Perf.Measure: instance Perf.Measure.Additive GHC.Types.Int
- Perf.Measure: instance Perf.Measure.Additive GHC.Word.Word64
- Perf.Measure: zero :: Additive a => a
- Perf: perf :: (MonadIO m, Additive b) => Text -> Measure m b -> m a -> PerfT m b a
+ Perf: perf :: (MonadIO m, Num b) => Text -> Measure m b -> m a -> PerfT m b a
- Perf.Measure: realtime :: Measure IO NominalDiffTime
+ Perf.Measure: realtime :: Measure IO Double
Files
- CHANGELOG.md +0/−5
- ChangeLog.md +4/−0
- perf.cabal +43/−64
- src/Perf.hs +7/−8
- src/Perf/Cycle.hs +26/−13
- src/Perf/Measure.hs +21/−38
- test/test.hs +0/−15
− CHANGELOG.md
@@ -1,5 +0,0 @@- 0.1- - * No Protolude, numhask dependencies- * No default langugage extensions in package.yaml- * No tdigest
+ ChangeLog.md view
@@ -0,0 +1,4 @@+0.8.0+===+* GHC 9.0.1 support+* internal fixes to remove numhask dependency
perf.cabal view
@@ -1,76 +1,55 @@-cabal-version: 2.4-name: perf-version: 0.7.0-synopsis: Low-level run time measurement.-description: A set of tools to accurately measure time performance of Haskell programs.- perf aims to be lightweight by having minimal dependencies on standard libraries.- See the Perf module for an example and full API documentation. -category: project-homepage: https://github.com/tonyday567/perf#readme-bug-reports: https://github.com/tonyday567/perf/issues-author: Tony Day, Marco Zocca-maintainer: tonyday567@gmail.com-copyright: Tony Day-license: BSD-3-Clause-license-file: LICENSE-build-type: Simple+cabal-version: 2.4+name: perf+version: 0.8.0+synopsis: Low-level run time measurement.+description:+ A set of tools to accurately measure time performance of Haskell programs.+ perf aims to be lightweight by having minimal dependencies on standard libraries.+ See the Perf module for an example and full API documentation. ++category: project+homepage: https://github.com/tonyday567/perf#readme+bug-reports: https://github.com/tonyday567/perf/issues+author: Tony Day, Marco Zocca+maintainer: tonyday567@gmail.com+copyright: Tony Day+license: BSD-3-Clause+license-file: LICENSE+build-type: Simple+tested-with: GHC ==8.8.4 || ==8.10.4 || ==9.0.1 || ==9.2.0.20210821 extra-source-files:- CHANGELOG.md+ ChangeLog.md source-repository head- type: git+ type: git location: https://github.com/tonyday567/perf library exposed-modules:- Perf- Perf.Measure- Perf.Cycle- hs-source-dirs:- src- ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints- build-depends:- base >=4.7 && <5,- containers >= 0.6,- deepseq >= 1.4,- foldl >= 1.4,- rdtsc >= 1.3,- text >= 1.2,- time >= 1.9,- transformers >= 0.5- default-language: Haskell2010- default-extensions:- NegativeLiterals- NoImplicitPrelude- OverloadedStrings- UnicodeSyntax+ Perf+ Perf.Cycle+ Perf.Measure++ hs-source-dirs: src ghc-options:- -Wall- -Wcompat- -Wincomplete-record-updates- -Wincomplete-uni-patterns- -Wredundant-constraints+ -Wall -Wcompat -Wincomplete-record-updates+ -Wincomplete-uni-patterns -Wredundant-constraints -fwrite-ide-info+ -hiedir=.hie -test-suite test- type: exitcode-stdio-1.0- main-is: test.hs- hs-source-dirs:- test build-depends:- base >=4.7 && <5,- deepseq >= 1.4,- doctest >= 0.16,- perf,- rdtsc >= 1.3- default-language: Haskell2010+ , base >=4.7 && <5+ , containers ^>=0.6+ , deepseq ^>=1.4+ , foldl ^>=1.4+ , mtl ^>=2.2.2+ , rdtsc ^>=1.3+ , text ^>=1.2+ , time ^>=1.9+ , transformers ^>=0.5++ default-language: Haskell2010 default-extensions:- NegativeLiterals- NoImplicitPrelude- OverloadedStrings- UnicodeSyntax ghc-options:- -Wall- -Wcompat- -Wincomplete-record-updates- -Wincomplete-uni-patterns- -Wredundant-constraints+ -Wall -Wcompat -Wincomplete-record-updates+ -Wincomplete-uni-patterns -Wredundant-constraints -fwrite-ide-info+ -hiedir=.hie
src/Perf.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RebindableSyntax #-} {-# OPTIONS_GHC -Wall #-} -- | == Introduction@@ -58,8 +59,7 @@ where import Control.Monad.IO.Class-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.State (StateT (..), evalStateT, execStateT, get, put, runStateT)+import Control.Monad.State.Lazy import Data.Functor.Identity import qualified Data.Map as Map import qualified Data.Text as T@@ -73,10 +73,9 @@ -- | PerfT is polymorphic in the type of measurement being performed. -- The monad stores and produces a Map of labelled measurement values-newtype PerfT m b a- = PerfT- { runPerf_ :: StateT (Map.Map T.Text b) m a- }+newtype PerfT m b a = PerfT+ { runPerf_ :: StateT (Map.Map T.Text b) m a+ } deriving (Functor, Applicative, Monad) -- | The obligatory transformer over Identity@@ -86,12 +85,12 @@ liftIO = PerfT . liftIO -- | Lift a monadic computation to a PerfT m, providing a label and a 'Measure'.-perf :: (MonadIO m, Additive b) => T.Text -> Measure m b -> m a -> PerfT m b a+perf :: (MonadIO m, Num b) => T.Text -> Measure m b -> m a -> PerfT m b a perf label m a = PerfT $ do st <- get (m', a') <- lift $ runMeasure m a- put $ Map.insertWith add label m' st+ put $ Map.insertWith (+) label m' st return a' -- | Lift a monadic computation to a PerfT m, and carry out the computation multiple times.
src/Perf/Cycle.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RebindableSyntax #-} {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -8,7 +9,7 @@ -- -- For reference, a computer with a frequency of 2 GHz means that one cycle is equivalent to 0.5 nanoseconds. module Perf.Cycle- ( -- $setup+ ( -- $usage Cycle, tick_, warmup,@@ -30,17 +31,29 @@ import Control.DeepSeq (NFData (..), force) import qualified Control.Foldl as L (fold, genericLength, premap, sum) import Control.Monad (replicateM)+import Data.Foldable (toList)+import Data.Sequence (Seq (..)) import GHC.Word (Word64) import System.CPUTime.Rdtsc import Prelude -- $setup -- >>> import Perf.Cycle+-- >>> import Control.Monad -- >>> import Data.Foldable (foldl')+-- >>> import qualified Control.Foldl as L -- >>> let n = 1000 -- >>> let a = 1000 -- >>> let f x = foldl' (+) 0 [1 .. x] +-- $usage+-- >>> import Perf.Cycle+-- >>> import Control.Monad+-- >>> import Data.Foldable (foldl')+-- >>> let n = 1000+-- >>> let a = 1000+-- >>> let f x = foldl' (+) 0 [1 .. x]+ -- | an unwrapped Word64 type Cycle = Word64 @@ -138,13 +151,13 @@ -- > fLambda :: Int -> Int -- > fLambda = \x -> foldl' (+) 0 [1 .. x] ticks :: NFData b => Int -> (a -> b) -> a -> IO ([Cycle], b)-ticks n0 f a = go f a n0 []+ticks n0 f a = go f a n0 Empty where go f' a' n ts- | n <= 0 = pure (reverse ts, f a)+ | n <= 0 = pure (toList ts, f a) | otherwise = do (t, _) <- tickNoinline f a- go f' a' (n - 1) (t : ts)+ go f' a' (n - 1) (ts :|> t) {-# NOINLINE ticks #-} -- | n measuremenst of a tickIO@@ -153,15 +166,15 @@ -- -- >>> (cs, fa) <- ticksIO n (pure $ f a) ticksIO :: (NFData a) => Int -> IO a -> IO ([Cycle], a)-ticksIO n0 a = go a n0 []+ticksIO n0 a = go a n0 Empty where go a' n ts | n <= 0 = do a'' <- a'- pure (reverse ts, a'')+ pure (toList ts, a'') | otherwise = do (t, _) <- tickIONoinline a'- go a' (n - 1) (t : ts)+ go a' (n - 1) (ts :|> t) {-# NOINLINE ticksIO #-} -- | make a series of measurements on a list of a's to be applied to f, for a tick function.@@ -210,24 +223,24 @@ -- | WHNF version ticksWHNF :: Int -> (a -> b) -> a -> IO ([Cycle], b)-ticksWHNF n0 f a = go f a n0 []+ticksWHNF n0 f a = go f a n0 Empty where go f' a' n ts- | n <= 0 = pure (reverse ts, f a)+ | n <= 0 = pure (toList ts, f a) | otherwise = do (t, _) <- tickWHNFNoinline f a- go f' a' (n - 1) (t : ts)+ go f' a' (n - 1) (ts :|> t) {-# NOINLINE ticksWHNF #-} -- | WHNF version ticksWHNFIO :: Int -> IO a -> IO ([Cycle], a)-ticksWHNFIO n0 a = go a n0 []+ticksWHNFIO n0 a = go a n0 Empty where go a' n ts | n <= 0 = do a'' <- a'- pure (reverse ts, a'')+ pure (toList ts, a'') | otherwise = do (t, _) <- tickWHNFIONoinline a'- go a' (n - 1) (t : ts)+ go a' (n - 1) (ts :|> t) {-# NOINLINE ticksWHNFIO #-}
src/Perf/Measure.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE StrictData #-} {-# OPTIONS_GHC -Wall #-}-{-# OPTIONS_GHC -fno-warn-orphans #-} -- | Specification of a performance measurement type suitable for the 'PerfT' monad transformer. module Perf.Measure@@ -13,39 +14,17 @@ realtime, count, cycles,- Additive (..), ) where -import Control.Monad (replicateM_)+import Control.Monad+import Data.Fixed (Fixed (MkFixed)) import Data.Time.Clock-import GHC.Word (Word64) import Perf.Cycle import System.CPUTime import System.CPUTime.Rdtsc import Prelude --- | Lightweight 'Additive' class.-class Num a => Additive a where- add :: a -> a -> a- zero :: a--instance Additive Int where- add = (+)- zero = 0--instance Additive Integer where- add = (+)- zero = 0--instance Additive Word64 where- add = (+)- zero = 0--instance Additive NominalDiffTime where- add = (+)- zero = 0- -- $setup -- >>> import Data.Foldable (foldl') @@ -54,14 +33,13 @@ -- For example, the measure specified below will return 1 every time measurement is requested, thus forming the base of a simple counter for loopy code. -- -- >>> let count = Measure 0 (pure ()) (pure 1)-data Measure m b- = forall a.- (Additive b) =>- Measure- { measure :: b,- prestep :: m a,- poststep :: a -> m b- }+data Measure m b = forall a.+ (Num b) =>+ Measure+ { measure :: b,+ prestep :: m a,+ poststep :: a -> m b+ } -- | Measure a single effect. --@@ -109,19 +87,24 @@ t <- getCPUTime return $ t - a --- | a measure using 'getCurrentTime' (unit is 'NominalDiffTime' which prints as seconds)+-- | a measure using 'getCurrentTime' (unit is seconds) -- -- >>> r <- runMeasure realtime (pure $ foldl' (+) 0 [0..1000]) ----- > (0.000046s,500500)-realtime :: Measure IO NominalDiffTime+-- > (0.000046,500500)+realtime :: Measure IO Double realtime = Measure m0 start stop where- m0 = zero :: NominalDiffTime+ m0 = 0 start = getCurrentTime stop a = do t <- getCurrentTime- return $ diffUTCTime t a+ return $ fromNominalDiffTime $ diffUTCTime t a++fromNominalDiffTime :: NominalDiffTime -> Double+fromNominalDiffTime t = fromInteger i * 1e-12+ where+ (MkFixed i) = nominalDiffTimeToSeconds t -- | a 'Measure' used to count iterations --
− test/test.hs
@@ -1,15 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--module Main where--import Test.DocTest-import Prelude--main :: IO ()-main = do- putStrLn "Perf.Cycle DocTest"- doctest ["src/Perf/Cycle.hs"]- putStrLn "Perf.Measure DocTest"- doctest ["src/Perf/Measure.hs"]- putStrLn "Perf DocTest"- doctest ["src/Perf.hs"]