{-# Language OverloadedStrings #-}

{-|
Module      : RtsStats
Description : Human readable interface to GHC RTS statistics
Copyright   : (c) Eric Mertens, 2017
License     : ISC
Maintainer  : emertens@gmail.com

-}

module RtsStats
  ( Stats
  , getStats
  , statsToEntries
  ) where

import Data.Int        (Int64)
import Data.List       (intercalate)
import Data.List.Split (chunksOf)
import Data.Text       (Text)
import Data.Text qualified as Text
import Data.Word       (Word32, Word64)
import GHC.Stats

class    Render a      where render :: a -> Text
instance Render Word32 where render :: Word32 -> Text
render = forall a. (Show a, Num a, Ord a) => a -> Text
prettyNum
instance Render Word64 where render :: Word64 -> Text
render = forall a. (Show a, Num a, Ord a) => a -> Text
prettyNum
instance Render Int64  where render :: RtsTime -> Text
render = forall a. (Show a, Num a, Ord a) => a -> Text
prettyNum
instance Render Double where render :: Double -> Text
render = [Char] -> Text
Text.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show

prettyNum :: Show a => Num a => Ord a => a -> Text
prettyNum :: forall a. (Show a, Num a, Ord a) => a -> Text
prettyNum a
n = [Char] -> Text
Text.pack ([Char] -> [Char]
addSign ([Char] -> [Char]
addCommas (forall a. Show a => a -> [Char]
show (forall a. Num a => a -> a
abs a
n))))
  where
    addSign :: [Char] -> [Char]
addSign = if a
n forall a. Ord a => a -> a -> Bool
< a
0 then (:) Char
'-' else forall a. a -> a
id

addCommas :: String -> String
addCommas :: [Char] -> [Char]
addCommas = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Int -> [e] -> [[e]]
chunksOf Int
3 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse

newtype Stats = Stats RTSStats

getStats :: IO (Maybe Stats)
getStats :: IO (Maybe Stats)
getStats =
  do Bool
enabled <- IO Bool
getRTSStatsEnabled
     if Bool
enabled then forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. RTSStats -> Stats
Stats forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO RTSStats
getRTSStats
                else forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing

statsToEntries :: Stats -> [(Text, Text)]
statsToEntries :: Stats -> [(Text, Text)]
statsToEntries (Stats RTSStats
rts) =
  let rgc :: GCDetails
rgc = RTSStats -> GCDetails
gc RTSStats
rts in seq :: forall a b. a -> b -> b
seq GCDetails
rgc
  [ (Text
"GCs"                                 , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word32
gcs                             RTSStats
rts)
  , (Text
"Major GCs"                           , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word32
major_gcs                       RTSStats
rts)
  , (Text
"Allocated bytes"                     , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
allocated_bytes                 RTSStats
rts)
  , (Text
"Max live bytes"                      , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
max_live_bytes                  RTSStats
rts)
  , (Text
"Max large objects bytes"             , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
max_large_objects_bytes         RTSStats
rts)
  , (Text
"Max compact bytes"                   , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
max_compact_bytes               RTSStats
rts)
  , (Text
"Max slop bytes"                      , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
max_slop_bytes                  RTSStats
rts)
  , (Text
"Max memory in use bytes"             , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
max_mem_in_use_bytes            RTSStats
rts)
  , (Text
"Cumulative live bytes"               , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
cumulative_live_bytes           RTSStats
rts)
  , (Text
"Copied bytes"                        , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
copied_bytes                    RTSStats
rts)
  , (Text
"Parallel copied bytes"               , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
par_copied_bytes                RTSStats
rts)
  , (Text
"Cumulative parallel max copied bytes", forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> Word64
cumulative_par_max_copied_bytes RTSStats
rts)
  , (Text
"Mutator CPU ns"                      , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
mutator_cpu_ns                  RTSStats
rts)
  , (Text
"Mutator elapsed ns"                  , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
mutator_elapsed_ns              RTSStats
rts)
  , (Text
"GC CPU ns"                           , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
gc_cpu_ns                       RTSStats
rts)
  , (Text
"GC elapsed ns"                       , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
gc_elapsed_ns                   RTSStats
rts)
  , (Text
"CPU ns"                              , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
cpu_ns                          RTSStats
rts)
  , (Text
"Elapsed ns"                          , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ RTSStats -> RtsTime
elapsed_ns                      RTSStats
rts)
  , (Text
"==[Totals]=="                        , Text
""                                          )
  , (Text
""                                    , Text
""                                          )
  , (Text
"Generation"                          , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word32
gcdetails_gen                   GCDetails
rgc)
  , (Text
"Threads"                             , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word32
gcdetails_threads               GCDetails
rgc)
  , (Text
"Allocated bytes"                     , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_allocated_bytes       GCDetails
rgc)
  , (Text
"Live bytes"                          , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_live_bytes            GCDetails
rgc)
  , (Text
"Large objects bytes"                 , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_large_objects_bytes   GCDetails
rgc)
  , (Text
"Compact bytes"                       , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_compact_bytes         GCDetails
rgc)
  , (Text
"Slop bytes"                          , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_slop_bytes            GCDetails
rgc)
  , (Text
"Memory in use bytes"                 , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_mem_in_use_bytes      GCDetails
rgc)
  , (Text
"Copied bytes"                        , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_copied_bytes          GCDetails
rgc)
  , (Text
"Parallel max copied bytes"           , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> Word64
gcdetails_par_max_copied_bytes  GCDetails
rgc)
  , (Text
"Sync elapsed ns"                     , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> RtsTime
gcdetails_sync_elapsed_ns       GCDetails
rgc)
  , (Text
"CPU ns"                              , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> RtsTime
gcdetails_cpu_ns                GCDetails
rgc)
  , (Text
"Elapsed ns"                          , forall a. Render a => a -> Text
render forall a b. (a -> b) -> a -> b
$ GCDetails -> RtsTime
gcdetails_elapsed_ns            GCDetails
rgc)
  , (Text
"==[Last GC]=="                       , Text
""                                          )
  ]