{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Mikan.Utils.Trace
(
traceEventIO
, traceMarkerIO
, getUserEra
, setUserEra
, incrementUserEra
, incrementUserEra_
) where
import Control.Monad.IO.Class
import Data.ByteString qualified as B
import Data.Functor ((<&>))
import Data.Text (Text)
import Data.Text.Encoding qualified as T
import GHC.Exts (Ptr(..), traceEvent#, traceMarker#)
import GHC.IO (IO(..))
import GHC.Profiling.Eras qualified as Eras
import GHC.RTS.Flags qualified as RTS
import Mikan.Utils.Monad
import System.IO.Unsafe
{-# NOINLINE userTracingEnabled #-}
userTracingEnabled :: Bool
userTracingEnabled :: Bool
userTracingEnabled =
IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (TraceFlags -> Bool
RTS.user (TraceFlags -> Bool) -> IO TraceFlags -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO TraceFlags
RTS.getTraceFlags)
{-# INLINE traceEventIO #-}
traceEventIO :: (MonadIO m) => Text -> m ()
traceEventIO :: forall (m :: * -> *). MonadIO m => Text -> m ()
traceEventIO Text
txt = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
Bool -> IO () -> IO ()
forall b (m :: * -> *). (IsBool b, Monad m) => b -> m () -> m ()
when Bool
userTracingEnabled (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
B.useAsCString (Text -> ByteString
T.encodeUtf8 Text
txt) \(Ptr Addr#
ptr) -> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO \State# RealWorld
s ->
case Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
traceEvent# Addr#
ptr State# RealWorld
s of
State# RealWorld
s' -> (# State# RealWorld
s', () #)
{-# INLINE traceMarkerIO #-}
traceMarkerIO :: (MonadIO m) => Text -> m ()
traceMarkerIO :: forall (m :: * -> *). MonadIO m => Text -> m ()
traceMarkerIO Text
txt = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
Bool -> IO () -> IO ()
forall b (m :: * -> *). (IsBool b, Monad m) => b -> m () -> m ()
when Bool
userTracingEnabled (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
B.useAsCString (Text -> ByteString
T.encodeUtf8 Text
txt) \(Ptr Addr#
ptr) -> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO \State# RealWorld
s ->
case Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
traceMarker# Addr#
ptr State# RealWorld
s of
State# RealWorld
s' -> (# State# RealWorld
s', () #)
{-# NOINLINE heapProfilingEnabled #-}
heapProfilingEnabled :: Bool
heapProfilingEnabled :: Bool
heapProfilingEnabled =
IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ IO ProfFlags
RTS.getProfFlags IO ProfFlags -> (ProfFlags -> Bool) -> IO Bool
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
RTS.ProfFlags { doHeapProfile :: ProfFlags -> DoHeapProfile
RTS.doHeapProfile = DoHeapProfile
RTS.NoHeapProfiling } -> Bool
False
ProfFlags
_ -> Bool
True
{-# INLINE getUserEra #-}
getUserEra :: (MonadIO m) => m Word
getUserEra :: forall (m :: * -> *). MonadIO m => m Word
getUserEra = IO Word -> m Word
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Word -> m Word) -> IO Word -> m Word
forall a b. (a -> b) -> a -> b
$
if Bool
heapProfilingEnabled then
IO Word
Eras.getUserEra
else
Word -> IO Word
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Word
0
{-# INLINE setUserEra #-}
setUserEra :: (MonadIO m) => Word -> m ()
setUserEra :: forall (m :: * -> *). MonadIO m => Word -> m ()
setUserEra Word
n = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
Bool -> IO () -> IO ()
forall b (m :: * -> *). (IsBool b, Monad m) => b -> m () -> m ()
when Bool
heapProfilingEnabled (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Word -> IO ()
Eras.setUserEra Word
n
{-# INLINE incrementUserEra_ #-}
incrementUserEra_ :: (MonadIO m) => Word -> m ()
incrementUserEra_ :: forall (m :: * -> *). MonadIO m => Word -> m ()
incrementUserEra_ Word
n = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
Bool -> IO () -> IO ()
forall b (m :: * -> *). (IsBool b, Monad m) => b -> m () -> m ()
when Bool
heapProfilingEnabled (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
IO Word -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Word -> IO ()) -> IO Word -> IO ()
forall a b. (a -> b) -> a -> b
$ Word -> IO Word
Eras.incrementUserEra Word
n
{-# INLINE incrementUserEra #-}
incrementUserEra :: (MonadIO m) => Word -> m Word
incrementUserEra :: forall (m :: * -> *). MonadIO m => Word -> m Word
incrementUserEra Word
n = IO Word -> m Word
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Word -> m Word) -> IO Word -> m Word
forall a b. (a -> b) -> a -> b
$
if Bool
heapProfilingEnabled then
Word -> IO Word
Eras.incrementUserEra Word
n
else
Word -> IO Word
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Word
0