Update base for new Safe Haskell design
[ghc.git] / libraries / base / GHC / Stats.hsc
1 {-# LANGUAGE Safe #-}
2 {-# LANGUAGE CPP #-}
3 {-# LANGUAGE ForeignFunctionInterface #-}
4 {-# LANGUAGE RecordWildCards #-}
5 {-# OPTIONS_GHC -funbox-strict-fields #-}
6
7 module GHC.Stats
8     ( GCStats(..)
9     , getGCStats
10 ) where
11
12 import Foreign.Marshal.Alloc
13 import Foreign.Storable
14 import Foreign.Ptr
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     , cpu_seconds :: !Double -- ^ Total CPU time elapsed since program start
48     , wall_seconds :: !Double -- ^ Total wall clock time elapsed since start
49     -- | Number of bytes copied during GC, minus space held by mutable
50     -- lists held by the capabilities.  Can be used with
51     -- 'par_max_bytes_copied' to determine how well parallel GC utilized
52     -- all cores.
53     , par_avg_bytes_copied :: !Int64
54     -- | Sum of number of bytes copied each GC by the most active GC
55     -- thread each GC.  The ratio of 'par_avg_bytes_copied' divided by
56     -- 'par_max_bytes_copied' approaches 1 for a maximally sequential
57     -- run and approaches the number of threads (set by the RTS flag
58     -- @-N@) for a maximally parallel run.
59     , par_max_bytes_copied :: !Int64
60     } deriving (Show, Read)
61
62     {-
63     , g_init_cpu_seconds :: !Double
64     , g_init_wall_seconds :: !Double
65     -}
66
67 -- | Retrieves garbage collection and memory statistics as of the last
68 -- garbage collection.  If you would like your statistics as recent as
69 -- possible, first run a 'performGC' from "System.Mem".
70 getGCStats :: IO GCStats
71 getGCStats = allocaBytes (#size GCStats) $ \p -> do
72     getGCStats_ p
73     bytes_allocated <- (# peek GCStats, bytes_allocated) p
74     num_gcs <- (# peek GCStats, num_gcs ) p
75     num_byte_usage_samples <- (# peek GCStats, num_byte_usage_samples ) p
76     max_bytes_used <- (# peek GCStats, max_bytes_used ) p
77     cumulative_bytes_used <- (# peek GCStats, cumulative_bytes_used ) p
78     bytes_copied <- (# peek GCStats, bytes_copied ) p
79     current_bytes_used <- (# peek GCStats, current_bytes_used ) p
80     current_bytes_slop <- (# peek GCStats, current_bytes_slop) p
81     max_bytes_slop <- (# peek GCStats, max_bytes_slop) p
82     peak_megabytes_allocated <- (# peek GCStats, peak_megabytes_allocated ) p
83     {-
84     init_cpu_seconds <- (# peek GCStats, init_cpu_seconds) p
85     init_wall_seconds <- (# peek GCStats, init_wall_seconds) p
86     -}
87     mutator_cpu_seconds <- (# peek GCStats, mutator_cpu_seconds) p
88     mutator_wall_seconds <- (# peek GCStats, mutator_wall_seconds) p
89     gc_cpu_seconds <- (# peek GCStats, gc_cpu_seconds) p
90     gc_wall_seconds <- (# peek GCStats, gc_wall_seconds) p
91     cpu_seconds <- (# peek GCStats, cpu_seconds) p
92     wall_seconds <- (# peek GCStats, wall_seconds) p
93     par_avg_bytes_copied <- (# peek GCStats, par_avg_bytes_copied) p
94     par_max_bytes_copied <- (# peek GCStats, par_max_bytes_copied) p
95     return GCStats { .. }
96
97 {-
98
99 -- Nontrivial to implement: TaskStats needs arbitrarily large
100 -- amounts of memory, spark stats wants to use SparkCounters
101 -- but that needs a new rts/ header.
102
103 data TaskStats = TaskStats
104     { task_mut_cpu_seconds :: Int64
105     , task_mut_wall_seconds :: Int64
106     , task_gc_cpu_seconds :: Int64
107     , task_gc_wall_seconds :: Int64
108     } deriving (Show, Read)
109
110 data SparkStats = SparkStats
111     { sparks_created :: Int64
112     , sparks_dud :: Int64
113     , sparks_overflowed :: Int64
114     , sparks_converted :: Int64
115     , sparks_gcd :: Int64
116     , sparks_fizzled :: Int64
117     } deriving (Show, Read)
118
119 -- We also could get per-generation stats, which requires a
120 -- non-constant but at runtime known about of memory.
121
122 -}