dist-install/build/GHC/Stats.hs

    {-# 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(..), RtsTime
        , 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
      } deriving (Read, Show)

    --
    -- | 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
      } deriving (Read, Show)

    -- | Time values from the RTS, using a fixed resolution of nanoseconds.
    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