New GHC.Stats module for accessing GC statistics.
[packages/base.git] / GHC / Stats.hsc
1 {-# LANGUAGE CPP #-}
2 {-# LANGUAGE ForeignFunctionInterface #-}
3 {-# LANGUAGE RecordWildCards #-}
4
5 module GHC.Stats
6     ( GCStats(..)
7     , getGCStats
8 ) where
9
10 import Foreign.C.Types
11 import Foreign.Marshal.Alloc
12 import Foreign.Storable
13 import Foreign.Ptr
14 import System.Mem
15 import Data.Int
16
17 #include "Rts.h"
18
19 foreign import ccall "getGCStats"    getGCStats_    :: Ptr () -> IO ()
20
21 -- I'm probably violating a bucket of constraints here... oops.
22
23 -- | Global garbage collection and memory statistics.
24 data GCStats = GCStats
25     { bytes_allocated :: Int64 -- ^ Total number of bytes allocated
26     , num_gcs :: Int64 -- ^ Number of garbage collections performed
27     , max_bytes_used :: Int64 -- ^ Maximum number of live bytes seen so far
28     , num_byte_usage_samples :: Int64 -- ^ Number of byte usage samples taken
29     -- | Sum of all byte usage samples, can be used with
30     -- 'num_byte_usage_samples' to calculate averages with
31     -- arbitrary weighting (if you are sampling this record multiple
32     -- times).
33     , cumulative_bytes_used :: Int64
34     , bytes_copied :: Int64 -- ^ Number of bytes copied during GC
35     , current_bytes_used :: Int64 -- ^ Current number of live bytes
36     , current_bytes_slop :: Int64 -- ^ Current number of bytes lost to slop
37     , max_bytes_slop :: Int64 -- ^ Maximum number of bytes lost to slop at any one time so far
38     , peak_megabytes_allocated :: Int64 -- ^ Maximum number of megabytes allocated
39     -- | CPU time spent running mutator threads.  This does not include
40     -- any profiling overhead or initialization.
41     , mutator_cpu_seconds :: Double
42     -- | Wall clock time spent running mutator threads.  This does not
43     -- include initialization.
44     , mutator_wall_seconds :: Double
45     , gc_cpu_seconds :: Double -- ^ CPU time spent running GC
46     , gc_wall_seconds :: Double -- ^ Wall clock time spent running GC
47     -- | Number of bytes copied during GC, minus space held by mutable
48     -- lists held by the capabilities.  Can be used with
49     -- 'par_max_bytes_copied' to determine how well parallel GC utilized
50     -- all cores.
51     , par_avg_bytes_copied :: Int64
52     -- | Sum of number of bytes copied each GC by the most active GC
53     -- thread each GC.  The ratio of 'par_avg_bytes_copied' divided by
54     -- 'par_max_bytes_copied' approaches 1 for a maximally sequential
55     -- run and approaches the number of threads (set by the RTS flag
56     -- @-N@) for a maximally parallel run.
57     , par_max_bytes_copied :: Int64
58     } deriving (Show, Read)
59
60     {-
61     , g_init_cpu_seconds :: Double
62     , g_init_wall_seconds :: Double
63     -}
64
65 -- | Retrieves garbage collection and memory statistics as of the last
66 -- garbage collection.  If you would like your statistics as recent as
67 -- possible, first run a 'performGC' from "System.Mem".
68 getGCStats = allocaBytes (#size GCStats) $ \p -> do
69     getGCStats_ p
70     bytes_allocated <- (# peek GCStats, bytes_allocated) p
71     num_gcs <- (# peek GCStats, num_gcs ) p
72     num_byte_usage_samples <- (# peek GCStats, num_byte_usage_samples ) p
73     max_bytes_used <- (# peek GCStats, max_bytes_used ) p
74     cumulative_bytes_used <- (# peek GCStats, cumulative_bytes_used ) p
75     bytes_copied <- (# peek GCStats, bytes_copied ) p
76     current_bytes_used <- (# peek GCStats, current_bytes_used ) p
77     current_bytes_slop <- (# peek GCStats, current_bytes_slop) p
78     max_bytes_slop <- (# peek GCStats, max_bytes_slop) p
79     peak_megabytes_allocated <- (# peek GCStats, peak_megabytes_allocated ) p
80     {-
81     init_cpu_seconds <- (# peek GCStats, init_cpu_seconds) p
82     init_wall_seconds <- (# peek GCStats, init_wall_seconds) p
83     -}
84     mutator_cpu_seconds <- (# peek GCStats, mutator_cpu_seconds) p
85     mutator_wall_seconds <- (# peek GCStats, mutator_wall_seconds) p
86     gc_cpu_seconds <- (# peek GCStats, gc_cpu_seconds) p
87     gc_wall_seconds <- (# peek GCStats, gc_wall_seconds) p
88     par_avg_bytes_copied <- (# peek GCStats, par_avg_bytes_copied) p
89     par_max_bytes_copied <- (# peek GCStats, par_max_bytes_copied) p
90     return GCStats { .. }
91
92 {-
93
94 -- Nontrivial to implement: TaskStats needs arbitrarily large
95 -- amounts of memory, spark stats wants to use SparkCounters
96 -- but that needs a new rts/ header.
97
98 data TaskStats = TaskStats
99     { task_mut_cpu_seconds :: Int64
100     , task_mut_wall_seconds :: Int64
101     , task_gc_cpu_seconds :: Int64
102     , task_gc_wall_seconds :: Int64
103     } deriving (Show, Read)
104
105 data SparkStats = SparkStats
106     { sparks_created :: Int64
107     , sparks_dud :: Int64
108     , sparks_overflowed :: Int64
109     , sparks_converted :: Int64
110     , sparks_gcd :: Int64
111     , sparks_fizzled :: Int64
112     } deriving (Show, Read)
113
114 -- We also could get per-generation stats, which requires a
115 -- non-constant but at runtime known about of memory.
116
117 -}