{-# LINE 1 "GHC/Stats.hsc" #-} {-# LANGUAGE Trustworthy #-} {-# LINE 2 "GHC/Stats.hsc" #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -funbox-strict-fields #-} ----------------------------------------------------------------------------- -- | This module provides access to internal garbage collection and -- memory usage statistics. These statistics are not available unless -- a program is run with the @-T@ RTS flag. -- -- This module is GHC-only and should not be considered portable. -- -- @since 4.5.0.0 ----------------------------------------------------------------------------- module GHC.Stats ( GCStats(..) , getGCStats , getGCStatsEnabled ) where import Control.Monad import Data.Int import GHC.Base import GHC.Read ( Read ) import GHC.Show ( Show ) import GHC.IO.Exception import Foreign.Marshal.Alloc import Foreign.Storable import Foreign.Ptr {-# LINE 32 "GHC/Stats.hsc" #-} foreign import ccall "getGCStats" getGCStats_ :: Ptr () -> IO () -- | Returns whether GC stats have been enabled (with @+RTS -T@, for example). -- -- @since 4.6.0.0 foreign import ccall "getGCStatsEnabled" getGCStatsEnabled :: IO Bool -- I'm probably violating a bucket of constraints here... oops. -- | Statistics about memory usage and the garbage collector. Apart from -- 'currentBytesUsed' and 'currentBytesSlop' all are cumulative values since -- the program started. -- -- @since 4.5.0.0 data GCStats = GCStats { -- | Total number of bytes allocated bytesAllocated :: !Int64 -- | Number of garbage collections performed (any generation, major and -- minor) , numGcs :: !Int64 -- | Maximum number of live bytes seen so far , maxBytesUsed :: !Int64 -- | Number of byte usage samples taken, or equivalently -- the number of major GCs performed. , numByteUsageSamples :: !Int64 -- | Sum of all byte usage samples, can be used with -- 'numByteUsageSamples' to calculate averages with -- arbitrary weighting (if you are sampling this record multiple -- times). , cumulativeBytesUsed :: !Int64 -- | Number of bytes copied during GC , bytesCopied :: !Int64 -- | Number of live bytes at the end of the last major GC , currentBytesUsed :: !Int64 -- | Current number of bytes lost to slop , currentBytesSlop :: !Int64 -- | Maximum number of bytes lost to slop at any one time so far , maxBytesSlop :: !Int64 -- | Maximum number of megabytes allocated , peakMegabytesAllocated :: !Int64 -- | CPU time spent running mutator threads. This does not include -- any profiling overhead or initialization. , mutatorCpuSeconds :: !Double -- | Wall clock time spent running mutator threads. This does not -- include initialization. , mutatorWallSeconds :: !Double -- | CPU time spent running GC , gcCpuSeconds :: !Double -- | Wall clock time spent running GC , gcWallSeconds :: !Double -- | Total CPU time elapsed since program start , cpuSeconds :: !Double -- | Total wall clock time elapsed since start , wallSeconds :: !Double -- | Number of bytes copied during GC, minus space held by mutable -- lists held by the capabilities. Can be used with -- 'parMaxBytesCopied' to determine how well parallel GC utilized -- all cores. , parTotBytesCopied :: !Int64 -- | Sum of number of bytes copied each GC by the most active GC -- thread each GC. The ratio of 'parTotBytesCopied' divided by -- 'parMaxBytesCopied' approaches 1 for a maximally sequential -- run and approaches the number of threads (set by the RTS flag -- @-N@) for a maximally parallel run. , parMaxBytesCopied :: !Int64 } deriving (Show, Read) {- , initCpuSeconds :: !Double , initWallSeconds :: !Double -} -- | Retrieves garbage collection and memory statistics as of the last -- garbage collection. If you would like your statistics as recent as -- possible, first run a 'System.Mem.performGC'. -- -- @since 4.5.0.0 getGCStats :: IO GCStats getGCStats = do statsEnabled <- getGCStatsEnabled unless statsEnabled . ioError $ IOError Nothing UnsupportedOperation "" "getGCStats: GC stats not enabled. Use `+RTS -T -RTS' to enable them." Nothing Nothing allocaBytes ((144)) $ \p -> do {-# LINE 123 "GHC/Stats.hsc" #-} getGCStats_ p bytesAllocated <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p {-# LINE 125 "GHC/Stats.hsc" #-} numGcs <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p {-# LINE 126 "GHC/Stats.hsc" #-} numByteUsageSamples <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p {-# LINE 127 "GHC/Stats.hsc" #-} maxBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) p {-# LINE 128 "GHC/Stats.hsc" #-} cumulativeBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) p {-# LINE 129 "GHC/Stats.hsc" #-} bytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) p {-# LINE 130 "GHC/Stats.hsc" #-} currentBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) p {-# LINE 131 "GHC/Stats.hsc" #-} currentBytesSlop <- ((\hsc_ptr -> peekByteOff hsc_ptr 56)) p {-# LINE 132 "GHC/Stats.hsc" #-} maxBytesSlop <- ((\hsc_ptr -> peekByteOff hsc_ptr 64)) p {-# LINE 133 "GHC/Stats.hsc" #-} peakMegabytesAllocated <- ((\hsc_ptr -> peekByteOff hsc_ptr 72)) p {-# LINE 134 "GHC/Stats.hsc" #-} {- initCpuSeconds <- (# peek GCStats, init_cpu_seconds) p initWallSeconds <- (# peek GCStats, init_wall_seconds) p -} mutatorCpuSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 96)) p {-# LINE 139 "GHC/Stats.hsc" #-} mutatorWallSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 104)) p {-# LINE 140 "GHC/Stats.hsc" #-} gcCpuSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 112)) p {-# LINE 141 "GHC/Stats.hsc" #-} gcWallSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 120)) p {-# LINE 142 "GHC/Stats.hsc" #-} cpuSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 128)) p {-# LINE 143 "GHC/Stats.hsc" #-} wallSeconds <- ((\hsc_ptr -> peekByteOff hsc_ptr 136)) p {-# LINE 144 "GHC/Stats.hsc" #-} parTotBytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) p {-# LINE 145 "GHC/Stats.hsc" #-} parMaxBytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 88)) p {-# LINE 146 "GHC/Stats.hsc" #-} return GCStats { .. } {- -- Nontrivial to implement: TaskStats needs arbitrarily large -- amounts of memory, spark stats wants to use SparkCounters -- but that needs a new rts/ header. data TaskStats = TaskStats { taskMutCpuSeconds :: Int64 , taskMutWallSeconds :: Int64 , taskGcCpuSeconds :: Int64 , taskGcWallSeconds :: Int64 } deriving (Show, Read) data SparkStats = SparkStats { sparksCreated :: Int64 , sparksDud :: Int64 , sparksOverflowed :: Int64 , sparksConverted :: Int64 , sparksGcd :: Int64 , sparksFizzled :: Int64 } deriving (Show, Read) -- We also could get per-generation stats, which requires a -- non-constant but at runtime known about of memory. -}