{-# LINE 1 "libraries/base/GHC/Stats.hsc" #-} {-# LANGUAGE Trustworthy #-} {-# 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 ( -- * Runtime statistics RTSStats(..), GCDetails(..) , getRTSStats , getRTSStatsEnabled -- * DEPRECATED, don't use , GCStats(..) , getGCStats , getGCStatsEnabled ) where import Control.Applicative import Control.Monad import Data.Int import Data.Word import GHC.Base import GHC.Num (Num(..)) import GHC.Real (quot, fromIntegral, (/)) import GHC.Read ( Read ) import GHC.Show ( Show ) import GHC.IO.Exception import Foreign.Marshal.Alloc import Foreign.Storable import Foreign.Ptr foreign import ccall "getRTSStats" getRTSStats_ :: Ptr () -> IO () -- | Returns whether GC stats have been enabled (with @+RTS -T@, for example). -- -- @since 4.9.0.0 foreign import ccall "getRTSStatsEnabled" getRTSStatsEnabled :: IO Bool -- -- | Statistics about runtime activity since the start of the -- program. This is a mirror of the C @struct RTSStats@ in @RtsAPI.h@ -- -- @since 4.9.0.0 -- data RTSStats = RTSStats { -- ----------------------------------- -- Cumulative stats about memory use -- | Total number of GCs gcs :: Word32 -- | Total number of major (oldest generation) GCs , major_gcs :: Word32 -- | Total bytes allocated , allocated_bytes :: Word64 -- | Maximum live data (including large objects + compact regions) , max_live_bytes :: Word64 -- | Maximum live data in large objects , max_large_objects_bytes :: Word64 -- | Maximum live data in compact regions , max_compact_bytes :: Word64 -- | Maximum slop , max_slop_bytes :: Word64 -- | Maximum memory in use by the RTS , max_mem_in_use_bytes :: Word64 -- | Sum of live bytes across all major GCs. Divided by major_gcs -- gives the average live data over the lifetime of the program. , cumulative_live_bytes :: Word64 -- | Sum of copied_bytes across all GCs , copied_bytes :: Word64 -- | Sum of copied_bytes across all parallel GCs , par_copied_bytes :: Word64 -- | Sum of par_max_copied_bytes across all parallel GCs , cumulative_par_max_copied_bytes :: Word64 -- ----------------------------------- -- Cumulative stats about time use -- (we use signed values here because due to inaccuracies in timers -- the values can occasionally go slightly negative) -- | Total CPU time used by the mutator , mutator_cpu_ns :: RtsTime -- | Total elapsed time used by the mutator , mutator_elapsed_ns :: RtsTime -- | Total CPU time used by the GC , gc_cpu_ns :: RtsTime -- | Total elapsed time used by the GC , gc_elapsed_ns :: RtsTime -- | Total CPU time (at the previous GC) , cpu_ns :: RtsTime -- | Total elapsed time (at the previous GC) , elapsed_ns :: RtsTime -- | Details about the most recent GC , gc :: GCDetails } -- -- | Statistics about a single GC. This is a mirror of the C @struct -- GCDetails@ in @RtsAPI.h@, with the field prefixed with @gc_@ to -- avoid collisions with 'RTSStats'. -- data GCDetails = GCDetails { -- | The generation number of this GC gcdetails_gen :: Word32 -- | Number of threads used in this GC , gcdetails_threads :: Word32 -- | Number of bytes allocated since the previous GC , gcdetails_allocated_bytes :: Word64 -- | Total amount of live data in the heap (incliudes large + compact data) , gcdetails_live_bytes :: Word64 -- | Total amount of live data in large objects , gcdetails_large_objects_bytes :: Word64 -- | Total amount of live data in compact regions , gcdetails_compact_bytes :: Word64 -- | Total amount of slop (wasted memory) , gcdetails_slop_bytes :: Word64 -- | Total amount of memory in use by the RTS , gcdetails_mem_in_use_bytes :: Word64 -- | Total amount of data copied during this GC , gcdetails_copied_bytes :: Word64 -- | In parallel GC, the max amount of data copied by any one thread , gcdetails_par_max_copied_bytes :: Word64 -- | The time elapsed during synchronisation before GC , gcdetails_sync_elapsed_ns :: RtsTime -- | The CPU time used during GC itself , gcdetails_cpu_ns :: RtsTime -- | The time elapsed during GC itself , gcdetails_elapsed_ns :: RtsTime } type RtsTime = Int64 -- @since 4.9.0.0 -- getRTSStats :: IO RTSStats getRTSStats = do statsEnabled <- getGCStatsEnabled unless statsEnabled . ioError $ IOError Nothing UnsupportedOperation "" "getGCStats: GC stats not enabled. Use `+RTS -T -RTS' to enable them." Nothing Nothing allocaBytes ((232)) $ \p -> do {-# LINE 159 "libraries/base/GHC/Stats.hsc" #-} getRTSStats_ p gcs <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p {-# LINE 161 "libraries/base/GHC/Stats.hsc" #-} major_gcs <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) p {-# LINE 162 "libraries/base/GHC/Stats.hsc" #-} allocated_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p {-# LINE 163 "libraries/base/GHC/Stats.hsc" #-} max_live_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p {-# LINE 164 "libraries/base/GHC/Stats.hsc" #-} max_large_objects_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) p {-# LINE 165 "libraries/base/GHC/Stats.hsc" #-} max_compact_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) p {-# LINE 166 "libraries/base/GHC/Stats.hsc" #-} max_slop_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) p {-# LINE 167 "libraries/base/GHC/Stats.hsc" #-} max_mem_in_use_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) p {-# LINE 168 "libraries/base/GHC/Stats.hsc" #-} cumulative_live_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 56)) p {-# LINE 169 "libraries/base/GHC/Stats.hsc" #-} copied_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 64)) p {-# LINE 170 "libraries/base/GHC/Stats.hsc" #-} par_copied_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 72)) p {-# LINE 171 "libraries/base/GHC/Stats.hsc" #-} cumulative_par_max_copied_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) p {-# LINE 173 "libraries/base/GHC/Stats.hsc" #-} mutator_cpu_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 88)) p {-# LINE 174 "libraries/base/GHC/Stats.hsc" #-} mutator_elapsed_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 96)) p {-# LINE 175 "libraries/base/GHC/Stats.hsc" #-} gc_cpu_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 104)) p {-# LINE 176 "libraries/base/GHC/Stats.hsc" #-} gc_elapsed_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 112)) p {-# LINE 177 "libraries/base/GHC/Stats.hsc" #-} cpu_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 120)) p {-# LINE 178 "libraries/base/GHC/Stats.hsc" #-} elapsed_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 128)) p {-# LINE 179 "libraries/base/GHC/Stats.hsc" #-} let pgc = ((\hsc_ptr -> hsc_ptr `plusPtr` 136)) p {-# LINE 180 "libraries/base/GHC/Stats.hsc" #-} gc <- do gcdetails_gen <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) pgc {-# LINE 182 "libraries/base/GHC/Stats.hsc" #-} gcdetails_threads <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) pgc {-# LINE 183 "libraries/base/GHC/Stats.hsc" #-} gcdetails_allocated_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) pgc {-# LINE 184 "libraries/base/GHC/Stats.hsc" #-} gcdetails_live_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) pgc {-# LINE 185 "libraries/base/GHC/Stats.hsc" #-} gcdetails_large_objects_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) pgc {-# LINE 187 "libraries/base/GHC/Stats.hsc" #-} gcdetails_compact_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) pgc {-# LINE 188 "libraries/base/GHC/Stats.hsc" #-} gcdetails_slop_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) pgc {-# LINE 189 "libraries/base/GHC/Stats.hsc" #-} gcdetails_mem_in_use_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) pgc {-# LINE 190 "libraries/base/GHC/Stats.hsc" #-} gcdetails_copied_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 56)) pgc {-# LINE 191 "libraries/base/GHC/Stats.hsc" #-} gcdetails_par_max_copied_bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 64)) pgc {-# LINE 193 "libraries/base/GHC/Stats.hsc" #-} gcdetails_sync_elapsed_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 72)) pgc {-# LINE 194 "libraries/base/GHC/Stats.hsc" #-} gcdetails_cpu_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) pgc {-# LINE 195 "libraries/base/GHC/Stats.hsc" #-} gcdetails_elapsed_ns <- ((\hsc_ptr -> peekByteOff hsc_ptr 88)) pgc {-# LINE 196 "libraries/base/GHC/Stats.hsc" #-} return GCDetails{..} return RTSStats{..} -- ----------------------------------------------------------------------------- -- DEPRECATED API -- 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 {-# DEPRECATED GCStats "Use RTSStats instead. This will be removed in GHC 8.4.1" #-} 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. , mblocksAllocated :: !Int64 -- ^ Number of allocated megablocks , 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) -- | 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 {-# DEPRECATED getGCStats "Use getRTSStats instead. This will be removed in GHC 8.4.1" #-} 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 ((232)) $ \p -> do {-# LINE 284 "libraries/base/GHC/Stats.hsc" #-} getRTSStats_ p bytesAllocated <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p {-# LINE 286 "libraries/base/GHC/Stats.hsc" #-} numGcs <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p {-# LINE 287 "libraries/base/GHC/Stats.hsc" #-} numByteUsageSamples <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) p {-# LINE 288 "libraries/base/GHC/Stats.hsc" #-} maxBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p {-# LINE 289 "libraries/base/GHC/Stats.hsc" #-} cumulativeBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 56)) p {-# LINE 290 "libraries/base/GHC/Stats.hsc" #-} bytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 64)) p {-# LINE 291 "libraries/base/GHC/Stats.hsc" #-} currentBytesUsed <- ((\hsc_ptr -> peekByteOff hsc_ptr 152)) p {-# LINE 292 "libraries/base/GHC/Stats.hsc" #-} currentBytesSlop <- ((\hsc_ptr -> peekByteOff hsc_ptr 176)) p {-# LINE 293 "libraries/base/GHC/Stats.hsc" #-} maxBytesSlop <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) p {-# LINE 294 "libraries/base/GHC/Stats.hsc" #-} peakMegabytesAllocated <- do bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) p {-# LINE 296 "libraries/base/GHC/Stats.hsc" #-} return (bytes `quot` (1024*1024)) mblocksAllocated <- do bytes <- ((\hsc_ptr -> peekByteOff hsc_ptr 184)) p {-# LINE 299 "libraries/base/GHC/Stats.hsc" #-} return (bytes `quot` (1024*1024)) mutatorCpuSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 88)) p {-# LINE 301 "libraries/base/GHC/Stats.hsc" #-} mutatorWallSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 96)) p {-# LINE 303 "libraries/base/GHC/Stats.hsc" #-} gcCpuSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 104)) p {-# LINE 304 "libraries/base/GHC/Stats.hsc" #-} gcWallSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 112)) p {-# LINE 305 "libraries/base/GHC/Stats.hsc" #-} cpuSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 120)) p {-# LINE 306 "libraries/base/GHC/Stats.hsc" #-} wallSeconds <- nsToSecs <$> ((\hsc_ptr -> peekByteOff hsc_ptr 128)) p {-# LINE 307 "libraries/base/GHC/Stats.hsc" #-} parTotBytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 72)) p {-# LINE 308 "libraries/base/GHC/Stats.hsc" #-} parMaxBytesCopied <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) p {-# LINE 309 "libraries/base/GHC/Stats.hsc" #-} return GCStats { .. } nsToSecs :: Int64 -> Double nsToSecs ns = fromIntegral ns / (1000000000) {-# LINE 313 "libraries/base/GHC/Stats.hsc" #-} {-# DEPRECATED getGCStatsEnabled "use getRTSStatsEnabled instead. This will be removed in GHC 8.4.1" #-} getGCStatsEnabled :: IO Bool getGCStatsEnabled = getRTSStatsEnabled