summaryrefslogtreecommitdiff
path: root/rts/Trace.h
diff options
context:
space:
mode:
authorDuncan Coutts <duncan@well-typed.com>2012-02-06 12:22:18 +0000
committerDuncan Coutts <duncan@well-typed.com>2012-04-04 19:10:44 +0100
commit65aaa9b2715c5245838123f3a0fa5d92e0a66bce (patch)
treec590a78588274f19285965d7b5cbd3b051a9329a /rts/Trace.h
parentcd930da1145a0d6094e5b5380034e80d002d5b9a (diff)
downloadhaskell-65aaa9b2715c5245838123f3a0fa5d92e0a66bce.tar.gz
Add new eventlog events for various heap and GC statistics
They cover much the same info as is available via the GHC.Stats module or via the '+RTS -s' textual output, but via the eventlog and with a better sampling frequency. We have three new generic heap info events and two very GHC-specific ones. (The hope is the general ones are usable by other implementations that use the same eventlog system, or indeed not so sensitive to changes in GHC itself.) The general ones are: * total heap mem allocated since prog start, on a per-HEC basis * current size of the heap (MBlocks reserved from OS for the heap) * current size of live data in the heap Currently these are all emitted by GHC at GC time (live data only at major GC). The GHC specific ones are: * an event giving various static heap paramaters: * number of generations (usually 2) * max size if any * nursary size * MBlock and block sizes * a event emitted on each GC containing: * GC generation (usually just 0,1) * total bytes copied * bytes lost to heap slop and fragmentation * the number of threads in the parallel GC (1 for serial) * the maximum number of bytes copied by any par GC thread * the total number of bytes copied by all par GC threads (these last three can be used to calculate an estimate of the work balance in parallel GCs)
Diffstat (limited to 'rts/Trace.h')
-rw-r--r--rts/Trace.h142
1 files changed, 140 insertions, 2 deletions
diff --git a/rts/Trace.h b/rts/Trace.h
index dcb0b00621..18856d9721 100644
--- a/rts/Trace.h
+++ b/rts/Trace.h
@@ -37,8 +37,9 @@ typedef StgWord16 CapsetType;
enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM,
CapsetTypeOsProcess = CAPSET_TYPE_OSPROCESS,
CapsetTypeClockdomain = CAPSET_TYPE_CLOCKDOMAIN };
-#define CAPSET_OSPROCESS_DEFAULT 0
-#define CAPSET_CLOCKDOMAIN_DEFAULT 1
+#define CAPSET_OSPROCESS_DEFAULT ((CapsetID)0)
+#define CAPSET_HEAP_DEFAULT ((CapsetID)0) /* reusing the same capset */
+#define CAPSET_CLOCKDOMAIN_DEFAULT ((CapsetID)1)
// -----------------------------------------------------------------------------
// Message classes
@@ -113,6 +114,35 @@ void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
void traceGcEvent_ (Capability *cap, EventTypeNum tag);
/*
+ * Record a heap event
+ */
+#define traceHeapEvent(cap, tag, heap_capset, info1) \
+ if (RTS_UNLIKELY(TRACE_gc)) { \
+ traceHeapEvent_(cap, tag, heap_capset, info1); \
+ }
+void traceHeapEvent_ (Capability *cap,
+ EventTypeNum tag,
+ CapsetID heap_capset,
+ lnat info1);
+
+void traceEventHeapInfo_ (CapsetID heap_capset,
+ nat gens,
+ lnat maxHeapSize,
+ lnat allocAreaSize,
+ lnat mblockSize,
+ lnat blockSize);
+
+void traceEventGcStats_ (Capability *cap,
+ CapsetID heap_capset,
+ nat gen,
+ lnat copied,
+ lnat slop,
+ lnat fragmentation,
+ nat par_n_threads,
+ lnat par_max_copied,
+ lnat par_tot_copied);
+
+/*
* Record a spark event
*/
#define traceSparkEvent(cap, tag) \
@@ -227,6 +257,13 @@ void traceSparkCounters_ (Capability *cap,
#define traceSchedEvent(cap, tag, tso, other) /* nothing */
#define traceSchedEvent2(cap, tag, tso, other, info) /* nothing */
#define traceGcEvent(cap, tag) /* nothing */
+#define traceEventGcStats_(cap, heap_capset, gen, \
+ copied, slop, fragmentation, \
+ par_n_threads, par_max_copied, par_tot_copied) /* nothing */
+#define traceHeapEvent(cap, tag, heap_capset, info1) /* nothing */
+#define traceEventHeapInfo_(heap_capset, gens, \
+ maxHeapSize, allocAreaSize, \
+ mblockSize, blockSize) /* nothing */
#define traceSparkEvent(cap, tag) /* nothing */
#define traceSparkEvent2(cap, tag, other) /* nothing */
#define traceCap(class, cap, msg, ...) /* nothing */
@@ -302,6 +339,31 @@ INLINE_HEADER void dtraceStartup (int num_caps) {
HASKELLEVENT_GC_WORK(cap)
#define dtraceGcDone(cap) \
HASKELLEVENT_GC_DONE(cap)
+#define dtraceEventGcStats(heap_capset, gens, \
+ copies, slop, fragmentation, \
+ par_n_threads, \
+ par_max_copied, \
+ par_tot_copied) \
+ HASKELLEVENT_GC_STATS(heap_capset, gens, \
+ copies, slop, fragmentation, \
+ par_n_threads, \
+ par_max_copied, \
+ par_tot_copied) \
+#define dtraceHeapInfo(heap_capset, gens, \
+ maxHeapSize, allocAreaSize, \
+ mblockSize, blockSize) \
+ HASKELLEVENT_HEAP_INFO(heap_capset, gens, \
+ maxHeapSize, allocAreaSize, \
+ mblockSize, blockSize)
+#define dtraceEventHeapAllocated(cap, heap_capset, \
+ allocated) \
+ HASKELLEVENT_HEAP_ALLOCATED(cap, heap_capset, \
+ allocated)
+#define dtraceEventHeapSize(heap_capset, size) \
+ HASKELLEVENT_HEAP_LIVE(heap_capset, size)
+#define dtraceEventHeapLive(heap_capset, live) \
+ HASKELLEVENT_HEAP_LIVE(heap_capset, live)
+
#define dtraceCapsetCreate(capset, capset_type) \
HASKELLEVENT_CAPSET_CREATE(capset, capset_type)
#define dtraceCapsetDelete(capset) \
@@ -346,6 +408,18 @@ INLINE_HEADER void dtraceStartup (int num_caps STG_UNUSED) {};
#define dtraceGcIdle(cap) /* nothing */
#define dtraceGcWork(cap) /* nothing */
#define dtraceGcDone(cap) /* nothing */
+#define dtraceEventGcStats(heap_capset, gens, \
+ copies, slop, fragmentation, \
+ par_n_threads, \
+ par_max_copied, \
+ par_tot_copied) /* nothing */
+#define dtraceHeapInfo(heap_capset, gens, \
+ maxHeapSize, allocAreaSize, \
+ mblockSize, blockSize) /* nothing */
+#define dtraceEventHeapAllocated(cap, heap_capset, \
+ allocated) /* nothing */
+#define dtraceEventHeapSize(heap_capset, size) /* nothing */
+#define dtraceEventHeapLive(heap_capset, live) /* nothing */
#define dtraceCapCreate(cap) /* nothing */
#define dtraceCapDelete(cap) /* nothing */
#define dtraceCapEnable(cap) /* nothing */
@@ -511,6 +585,70 @@ INLINE_HEADER void traceEventGcDone(Capability *cap STG_UNUSED)
dtraceGcDone((EventCapNo)cap->no);
}
+INLINE_HEADER void traceEventGcStats(Capability *cap STG_UNUSED,
+ CapsetID heap_capset STG_UNUSED,
+ nat gen STG_UNUSED,
+ lnat copied STG_UNUSED,
+ lnat slop STG_UNUSED,
+ lnat fragmentation STG_UNUSED,
+ nat par_n_threads STG_UNUSED,
+ lnat par_max_copied STG_UNUSED,
+ lnat par_tot_copied STG_UNUSED)
+{
+ if (RTS_UNLIKELY(TRACE_gc)) {
+ traceEventGcStats_(cap, heap_capset, gen,
+ copied, slop, fragmentation,
+ par_n_threads, par_max_copied, par_tot_copied);
+ }
+ dtraceEventGcStats(heap_capset, gens,
+ copies, slop, fragmentation,
+ par_n_threads, par_max_copied, par_tot_copied);
+}
+
+INLINE_HEADER void traceEventHeapInfo(CapsetID heap_capset STG_UNUSED,
+ nat gens STG_UNUSED,
+ lnat maxHeapSize STG_UNUSED,
+ lnat allocAreaSize STG_UNUSED,
+ lnat mblockSize STG_UNUSED,
+ lnat blockSize STG_UNUSED)
+{
+ if (RTS_UNLIKELY(TRACE_gc)) {
+ traceEventHeapInfo_(heap_capset, gens,
+ maxHeapSize, allocAreaSize,
+ mblockSize, blockSize);
+ }
+ dtraceHeapInfo(heap_capset, gens,
+ maxHeapSize, allocAreaSize,
+ mblockSize, blockSize);
+}
+
+INLINE_HEADER void traceEventHeapAllocated(Capability *cap STG_UNUSED,
+ CapsetID heap_capset STG_UNUSED,
+ lnat allocated STG_UNUSED)
+{
+ traceHeapEvent(cap, EVENT_HEAP_ALLOCATED, heap_capset, allocated);
+ dtraceEventHeapAllocated((EventCapNo)cap->no, heap_capset, allocated);
+}
+
+INLINE_HEADER void traceEventHeapSize(Capability *cap STG_UNUSED,
+ CapsetID heap_capset STG_UNUSED,
+ lnat heap_size STG_UNUSED)
+{
+ traceHeapEvent(cap, EVENT_HEAP_SIZE, heap_capset, heap_size);
+ dtraceEventHeapSize(heap_capset, heap_size);
+}
+
+INLINE_HEADER void traceEventHeapLive(Capability *cap STG_UNUSED,
+ CapsetID heap_capset STG_UNUSED,
+ lnat heap_live STG_UNUSED)
+{
+ traceHeapEvent(cap, EVENT_HEAP_LIVE, heap_capset, heap_live);
+ dtraceEventHeapLive(heap_capset, heap_live);
+}
+
+/* TODO: at some point we should remove this event, it's covered by
+ * the cap create/delete events.
+ */
INLINE_HEADER void traceEventStartup(void)
{
int n_caps;