{-# LANGUAGE NumericUnderscores #-}

module CodeGen.TimedValue where

import System.CPUTime (getCPUTime)

data TimedValue a = TimedValue
  { forall a. TimedValue a -> a
value :: a,
    forall a. TimedValue a -> Nanoseconds
time :: Nanoseconds
  }

-- | Nanoseconds, son!
newtype Nanoseconds = Nanoseconds Integer
  deriving (Int -> Nanoseconds -> ShowS
[Nanoseconds] -> ShowS
Nanoseconds -> String
(Int -> Nanoseconds -> ShowS)
-> (Nanoseconds -> String)
-> ([Nanoseconds] -> ShowS)
-> Show Nanoseconds
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Nanoseconds -> ShowS
showsPrec :: Int -> Nanoseconds -> ShowS
$cshow :: Nanoseconds -> String
show :: Nanoseconds -> String
$cshowList :: [Nanoseconds] -> ShowS
showList :: [Nanoseconds] -> ShowS
Show)

measureTimedValue :: IO a -> IO (TimedValue a)
measureTimedValue :: forall a. IO a -> IO (TimedValue a)
measureTimedValue IO a
computation = do
  Integer
start <- IO Integer
getCPUTime
  a
val <- IO a
computation
  Integer
end <- IO Integer
getCPUTime
  let t :: Nanoseconds
t = Integer -> Nanoseconds
Nanoseconds (Integer -> Nanoseconds) -> Integer -> Nanoseconds
forall a b. (a -> b) -> a -> b
$ (Integer
end Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
start) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
1_000
  TimedValue a -> IO (TimedValue a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (TimedValue a -> IO (TimedValue a))
-> TimedValue a -> IO (TimedValue a)
forall a b. (a -> b) -> a -> b
$ a -> Nanoseconds -> TimedValue a
forall a. a -> Nanoseconds -> TimedValue a
TimedValue a
val Nanoseconds
t

measureTime :: IO () -> IO Nanoseconds
measureTime :: IO () -> IO Nanoseconds
measureTime IO ()
computation = TimedValue () -> Nanoseconds
forall a. TimedValue a -> Nanoseconds
time (TimedValue () -> Nanoseconds)
-> IO (TimedValue ()) -> IO Nanoseconds
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO () -> IO (TimedValue ())
forall a. IO a -> IO (TimedValue a)
measureTimedValue IO ()
computation