3 | import public Data.DPair
4 | import public Data.Nat
5 | import public Data.Vect
6 | import public System.Clock
15 | data Format = Table | Details
26 | {auto 0 prf : IsSucc val}
29 | Eq Pos where (==) = (==) `on` val
32 | Ord Pos where compare = compare `on` val
35 | fromInteger : (n : Integer) -> (0 prf : IsSucc (cast n)) => Pos
36 | fromInteger n = MkPos (cast n)
44 | record Benchmarkable (err : Type) where
45 | constructor MkBenchmarkable
46 | {0 environment : Type}
52 | allocEnv : Pos -> IO environment
56 | cleanEnv : Pos -> environment -> IO ()
60 | runRepeatedly : environment -> Pos -> IO (Either err result)
66 | repeatedly_ : Nat -> PrimIO (Either err ()) -> PrimIO (Either err ())
67 | repeatedly_ 0 _ w = MkIORes (Right ()) w
68 | repeatedly_ (S k) f w =
69 | let MkIORes (Right _) w2 := f w | res => res
70 | in repeatedly_ k f w2
76 | repeatedly : Pos -> IO (Either err ()) -> IO (Either err ())
77 | repeatedly (MkPos n) io = fromPrim $
repeatedly_ n (toPrim io)
80 | singleIO : IO () -> Benchmarkable Void
83 | { allocEnv = \_ => pure ()
84 | , cleanEnv = \_,_ => pure ()
85 | , runRepeatedly = \(),n => repeatedly n (map Right io)
89 | repeatedlyPure_ : Nat -> a -> (() -> Either err a) -> Either err a
90 | repeatedlyPure_ 0 v _ = Right v
91 | repeatedlyPure_ (S k) v f = case f () of
92 | Right v2 => repeatedlyPure_ k v2 f
93 | Left err => Left err
96 | repeatedlyPure : Pos -> (() -> Either err a) -> Either err a
97 | repeatedlyPure (MkPos $
S n) f = case f () of
98 | Left err => Left err
99 | Right v => repeatedlyPure_ n v f
102 | singlePure : (() -> Either err a) -> Benchmarkable err
105 | { allocEnv = \_ => pure ()
106 | , cleanEnv = \_,_ => pure ()
107 | , runRepeatedly = \(),n => map (`repeatedlyPure` f) (pure n)
112 | basic : (a -> b) -> a -> Benchmarkable Void
113 | basic f va = singlePure (\_ => let v = f va in Right v)
120 | data Benchmark : (err : Type) -> Type where
121 | Single : (name : String) -> (bench : Benchmarkable err) -> Benchmark err
122 | Group : (name : String) -> (benchs : List (Benchmark err)) -> Benchmark err
125 | addPrefix : (pre : String) -> (rst : String) -> String
126 | addPrefix "" rst = rst
127 | addPrefix pre rst = "\{pre}/\{rst}"
141 | times : SUnit -> SUnit -> SUnit
144 | times (U 0 0) u = u
145 | times (U a1 r1) (U a2 r2) = U (a1 + a2) (r1 + r2)
148 | div : SUnit -> SUnit -> SUnit
152 | div (U a1 r1) (U a2 r2) = U (a1 - a2) (r1 - r2)
155 | record Scalar (u : SUnit) where
156 | constructor MkScalar
160 | Eq (Scalar u) where (==) = (==) `on` val
163 | Ord (Scalar u) where compare = compare `on` val
167 | fromInteger : Integer -> Scalar u
168 | fromInteger = MkScalar
171 | 0 AttoSeconds : Type
172 | AttoSeconds = Scalar (U 1 0)
175 | 0 AttoSecondsPerRun : Type
176 | AttoSecondsPerRun = Scalar (U 1 (-
1))
180 | Runs = Scalar (U 0 1)
183 | plus : Scalar u -> Scalar u -> Scalar u
184 | plus x y = MkScalar $
x.val + y.val
187 | minus : Scalar u -> Scalar u -> Scalar u
188 | minus x y = MkScalar $
x.val - y.val
191 | scalarSum : Foldable t => t (Scalar u) -> Scalar u
192 | scalarSum = foldl plus 0
195 | mult : Scalar u1 -> Scalar u2 -> Scalar (times u1 u2)
196 | mult x y = MkScalar $
x.val * y.val
199 | div : Scalar u1 -> Scalar u2 -> Scalar (div u1 u2)
200 | div x y = MkScalar $
x.val `div` y.val
203 | posLength : Vect (S n) a -> Scalar (U 0 0)
204 | posLength = MkScalar . cast . length
207 | fromFemtoSeconds : Integer -> AttoSeconds
208 | fromFemtoSeconds = fromInteger . (* 1000)
211 | fromPicoSeconds : Integer -> AttoSeconds
212 | fromPicoSeconds = fromFemtoSeconds . (* 1000)
215 | fromNanoSeconds : Integer -> AttoSeconds
216 | fromNanoSeconds = fromPicoSeconds . (* 1000)
219 | fromMicroSeconds : Integer -> AttoSeconds
220 | fromMicroSeconds = fromNanoSeconds . (* 1000)
223 | fromMilliSeconds : Integer -> AttoSeconds
224 | fromMilliSeconds = fromMicroSeconds . (* 1000)
227 | fromSeconds : Integer -> AttoSeconds
228 | fromSeconds = fromMilliSeconds . (* 1000)
231 | fromClock : Clock Duration -> AttoSeconds
234 | (fromNanoSeconds $
nanoseconds c)
235 | (fromSeconds $
seconds c)
238 | timeDelta : Clock t -> Clock t -> AttoSeconds
239 | timeDelta c1 c2 = fromClock $
timeDifference (max c1 c2) (min c1 c2)
242 | toFloat : Scalar u -> Double
243 | toFloat = cast . val
251 | record Measured where
252 | constructor MkMeasured
260 | startTime : Clock Monotonic
263 | stopTime : Clock Monotonic
266 | totalTime : AttoSeconds
269 | avrgTime : AttoSecondsPerRun
272 | cpuTime : AttoSeconds
275 | avrgCPU : AttoSecondsPerRun
278 | tot : Measured -> AttoSeconds
279 | tot m = if m.cpuOnly then m.cpuTime else m.totalTime
282 | avrg : Measured -> AttoSecondsPerRun
283 | avrg m = if m.cpuOnly then m.avrgCPU else m.avrgTime
290 | record Result where
291 | constructor MkResult
293 | runs : List Measured