5108dd3a292ab3e30bb63cef33ad25bc761ac5dd
[packages/base.git] / GHC / Stats.hsc
1 {-# LANGUAGE Safe #-}
2 {-# LANGUAGE CPP #-}
3 {-# LANGUAGE ForeignFunctionInterface #-}
4 {-# LANGUAGE RecordWildCards #-}
5 {-# OPTIONS_GHC -funbox-strict-fields #-}
6
7 -----------------------------------------------------------------------------
8 -- | This module provides access to internal garbage collection and
9 -- memory usage statistics.  These statistics are not available unless
10 -- a program is run with the @-T@ RTS flag.
11 --
12 -- This module is GHC-only and should not be considered portable.
13 --
14 -----------------------------------------------------------------------------
15 module GHC.Stats
16     ( GCStats(..)
17     , getGCStats
18     , getGCStatsEnabled
19 ) where
20
21 import Control.Monad
22 import Data.Int
23 import GHC.IO.Exception
24 import Foreign.Marshal.Alloc
25 import Foreign.Storable
26 import Foreign.Ptr
27
28 #include "Rts.h"
29
30 foreign import ccall "getGCStats"        getGCStats_       :: Ptr () -> IO ()
31
32 -- | Returns whether GC stats have been enabled (with @+RTS -T@, for example).
33 --
34 -- /Since: 4.6.0.0/
35 foreign import ccall "getGCStatsEnabled" getGCStatsEnabled :: IO Bool
36
37 -- I'm probably violating a bucket of constraints here... oops.
38
39 -- | Global garbage collection and memory statistics.
40 data GCStats = GCStats
41     { bytesAllocated :: !Int64 -- ^ Total number of bytes allocated
42     , numGcs :: !Int64 -- ^ Number of garbage collections performed
43     , maxBytesUsed :: !Int64 -- ^ Maximum number of live bytes seen so far
44     , numByteUsageSamples :: !Int64 -- ^ Number of byte usage samples taken
45     -- | Sum of all byte usage samples, can be used with
46     -- 'numByteUsageSamples' to calculate averages with
47     -- arbitrary weighting (if you are sampling this record multiple
48     -- times).
49     , cumulativeBytesUsed :: !Int64
50     , bytesCopied :: !Int64 -- ^ Number of bytes copied during GC
51     , currentBytesUsed :: !Int64 -- ^ Current number of live bytes
52     , currentBytesSlop :: !Int64 -- ^ Current number of bytes lost to slop
53     , maxBytesSlop :: !Int64 -- ^ Maximum number of bytes lost to slop at any one time so far
54     , peakMegabytesAllocated :: !Int64 -- ^ Maximum number of megabytes allocated
55     -- | CPU time spent running mutator threads.  This does not include
56     -- any profiling overhead or initialization.
57     , mutatorCpuSeconds :: !Double
58     -- | Wall clock time spent running mutator threads.  This does not
59     -- include initialization.
60     , mutatorWallSeconds :: !Double
61     , gcCpuSeconds :: !Double -- ^ CPU time spent running GC
62     , gcWallSeconds :: !Double -- ^ Wall clock time spent running GC
63     , cpuSeconds :: !Double -- ^ Total CPU time elapsed since program start
64     , wallSeconds :: !Double -- ^ Total wall clock time elapsed since start
65     -- | Number of bytes copied during GC, minus space held by mutable
66     -- lists held by the capabilities.  Can be used with
67     -- 'parMaxBytesCopied' to determine how well parallel GC utilized
68     -- all cores.
69     , parTotBytesCopied :: !Int64
70     -- | Sum of number of bytes copied each GC by the most active GC
71     -- thread each GC.  The ratio of 'parTotBytesCopied' divided by
72     -- 'parMaxBytesCopied' approaches 1 for a maximally sequential
73     -- run and approaches the number of threads (set by the RTS flag
74     -- @-N@) for a maximally parallel run.
75     , parMaxBytesCopied :: !Int64
76     } deriving (Show, Read)
77
78     {-
79     , initCpuSeconds :: !Double
80     , initWallSeconds :: !Double
81     -}
82
83 -- | Retrieves garbage collection and memory statistics as of the last
84 -- garbage collection.  If you would like your statistics as recent as
85 -- possible, first run a 'System.Mem.performGC'.
86 getGCStats :: IO GCStats
87 getGCStats = do
88   statsEnabled <- getGCStatsEnabled
89   unless statsEnabled .  ioError $ IOError
90     Nothing
91     UnsupportedOperation
92     ""
93     "getGCStats: GC stats not enabled. Use `+RTS -T -RTS' to enable them."
94     Nothing
95     Nothing
96   allocaBytes (#size GCStats) $ \p -> do
97     getGCStats_ p
98     bytesAllocated <- (# peek GCStats, bytes_allocated) p
99     numGcs <- (# peek GCStats, num_gcs ) p
100     numByteUsageSamples <- (# peek GCStats, num_byte_usage_samples ) p
101     maxBytesUsed <- (# peek GCStats, max_bytes_used ) p
102     cumulativeBytesUsed <- (# peek GCStats, cumulative_bytes_used ) p
103     bytesCopied <- (# peek GCStats, bytes_copied ) p
104     currentBytesUsed <- (# peek GCStats, current_bytes_used ) p
105     currentBytesSlop <- (# peek GCStats, current_bytes_slop) p
106     maxBytesSlop <- (# peek GCStats, max_bytes_slop) p
107     peakMegabytesAllocated <- (# peek GCStats, peak_megabytes_allocated ) p
108     {-
109     initCpuSeconds <- (# peek GCStats, init_cpu_seconds) p
110     initWallSeconds <- (# peek GCStats, init_wall_seconds) p
111     -}
112     mutatorCpuSeconds <- (# peek GCStats, mutator_cpu_seconds) p
113     mutatorWallSeconds <- (# peek GCStats, mutator_wall_seconds) p
114     gcCpuSeconds <- (# peek GCStats, gc_cpu_seconds) p
115     gcWallSeconds <- (# peek GCStats, gc_wall_seconds) p
116     cpuSeconds <- (# peek GCStats, cpu_seconds) p
117     wallSeconds <- (# peek GCStats, wall_seconds) p
118     parTotBytesCopied <- (# peek GCStats, par_tot_bytes_copied) p
119     parMaxBytesCopied <- (# peek GCStats, par_max_bytes_copied) p
120     return GCStats { .. }
121
122 {-
123
124 -- Nontrivial to implement: TaskStats needs arbitrarily large
125 -- amounts of memory, spark stats wants to use SparkCounters
126 -- but that needs a new rts/ header.
127
128 data TaskStats = TaskStats
129     { taskMutCpuSeconds :: Int64
130     , taskMutWallSeconds :: Int64
131     , taskGcCpuSeconds :: Int64
132     , taskGcWallSeconds :: Int64
133     } deriving (Show, Read)
134
135 data SparkStats = SparkStats
136     { sparksCreated :: Int64
137     , sparksDud :: Int64
138     , sparksOverflowed :: Int64
139     , sparksConverted :: Int64
140     , sparksGcd :: Int64
141     , sparksFizzled :: Int64
142     } deriving (Show, Read)
143
144 -- We also could get per-generation stats, which requires a
145 -- non-constant but at runtime known about of memory.
146
147 -}