summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/rts/EventLogFormat.h16
-rw-r--r--rts/RtsFlags.c2
-rw-r--r--rts/RtsProbes.d5
-rw-r--r--rts/Stats.c26
-rw-r--r--rts/Stats.h6
-rw-r--r--rts/Trace.c41
-rw-r--r--rts/Trace.h142
-rw-r--r--rts/eventlog/EventLog.c125
-rw-r--r--rts/eventlog/EventLog.h25
-rw-r--r--rts/sm/GC.c6
-rw-r--r--rts/sm/Storage.c7
11 files changed, 386 insertions, 15 deletions
diff --git a/includes/rts/EventLogFormat.h b/includes/rts/EventLogFormat.h
index afa1961a36..94f781dcb5 100644
--- a/includes/rts/EventLogFormat.h
+++ b/includes/rts/EventLogFormat.h
@@ -147,8 +147,18 @@
#define EVENT_CAP_DELETE 46 /* (cap) */
#define EVENT_CAP_DISABLE 47 /* (cap) */
#define EVENT_CAP_ENABLE 48 /* (cap) */
-
-/* Range 49 - 59 is available for new GHC and common events */
+#define EVENT_HEAP_ALLOCATED 49 /* (heap_capset, alloc_bytes) */
+#define EVENT_HEAP_SIZE 50 /* (heap_capset, size_bytes) */
+#define EVENT_HEAP_LIVE 51 /* (heap_capset, live_bytes) */
+#define EVENT_HEAP_INFO_GHC 52 /* (heap_capset, n_generations,
+ max_heap_size, alloc_area_size,
+ mblock_size, block_size) */
+#define EVENT_GC_STATS_GHC 53 /* (heap_capset, generation,
+ copied_bytes, slop_bytes, frag_bytes,
+ par_n_threads,
+ par_max_copied, par_tot_copied) */
+
+/* Range 54 - 59 is available for new GHC and common events */
/* Range 60 - 80 is used by eden for parallel tracing
* see http://www.mathematik.uni-marburg.de/~eden/
@@ -161,7 +171,7 @@
* ranges higher than this are reserved but not currently emitted by ghc.
* This must match the size of the EventDesc[] array in EventLog.c
*/
-#define NUM_GHC_EVENT_TAGS 49
+#define NUM_GHC_EVENT_TAGS 54
#if 0 /* DEPRECATED EVENTS: */
/* we don't actually need to record the thread, it's implicit */
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index 5afaf4914b..320a1b2350 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -305,7 +305,7 @@ usage_text[] = {
# endif
" where [flags] can contain:",
" s scheduler events",
-" g GC events",
+" g GC and heap events",
" p par spark events (sampled)",
" f par spark events (full detail)",
" u user events (emitted from Haskell code)",
diff --git a/rts/RtsProbes.d b/rts/RtsProbes.d
index 0921c98397..8d24f3a9ca 100644
--- a/rts/RtsProbes.d
+++ b/rts/RtsProbes.d
@@ -55,6 +55,11 @@ provider HaskellEvent {
probe gc__idle (EventCapNo);
probe gc__work (EventCapNo);
probe gc__done (EventCapNo);
+ probe gc__stats (CapsetID, StgWord, StgWord, StgWord, StgWord, StgWord, StgWord, StgWord);
+ probe heap__info (CapsetID, StgWord, StgWord, StgWord, StgWord, StgWord);
+ probe heap__allocated (EventCapNo, CapsetID, StgWord64);
+ probe heap__size (CapsetID, StgWord);
+ probe heap__live (CapsetID, StgWord);
/* capability events */
probe startup (EventCapNo);
diff --git a/rts/Stats.c b/rts/Stats.c
index 2277958557..a7335531ce 100644
--- a/rts/Stats.c
+++ b/rts/Stats.c
@@ -330,9 +330,9 @@ stat_gcWorkerThreadDone (gc_thread *gct STG_UNUSED)
-------------------------------------------------------------------------- */
void
-stat_endGC (gc_thread *gct,
- lnat alloc, lnat live, lnat copied, nat gen,
- lnat par_max_copied, lnat par_tot_copied, lnat slop)
+stat_endGC (Capability *cap, gc_thread *gct,
+ lnat alloc, lnat live, lnat copied, lnat slop, nat gen,
+ nat par_n_threads, lnat par_max_copied, lnat par_tot_copied)
{
if (RtsFlags.GcFlags.giveStats != NO_GC_STATS ||
RtsFlags.ProfFlags.doHeapProfile)
@@ -388,9 +388,26 @@ stat_endGC (gc_thread *gct,
lnat n;
for (n = 0; n < n_capabilities; n++) {
tot_alloc += capabilities[n].total_allocated;
+ traceEventHeapAllocated(&capabilities[n],
+ CAPSET_HEAP_DEFAULT,
+ capabilities[n].total_allocated * sizeof(W_));
}
ASSERT(GC_tot_alloc == tot_alloc);
}
+ traceEventHeapSize(cap,
+ CAPSET_HEAP_DEFAULT,
+ mblocks_allocated * MBLOCK_SIZE_W * sizeof(W_));
+ traceEventGcStats(cap,
+ CAPSET_HEAP_DEFAULT,
+ gen,
+ copied * sizeof(W_),
+ slop * sizeof(W_),
+ /* current loss due to fragmentation */
+ (mblocks_allocated * BLOCKS_PER_MBLOCK - n_alloc_blocks)
+ * BLOCK_SIZE_W * sizeof(W_),
+ par_n_threads,
+ par_max_copied * sizeof(W_),
+ par_tot_copied * sizeof(W_));
if (gen == RtsFlags.GcFlags.generations-1) { /* major GC? */
if (live > max_residency) {
@@ -399,6 +416,9 @@ stat_endGC (gc_thread *gct,
current_residency = live;
residency_samples++;
cumulative_residency += live;
+ traceEventHeapLive(cap,
+ CAPSET_HEAP_DEFAULT,
+ live * sizeof(W_));
}
if (slop > max_slop) max_slop = slop;
diff --git a/rts/Stats.h b/rts/Stats.h
index 83b2cb6998..63a1801236 100644
--- a/rts/Stats.h
+++ b/rts/Stats.h
@@ -19,9 +19,9 @@ void stat_startInit(void);
void stat_endInit(void);
void stat_startGC(struct gc_thread_ *gct);
-void stat_endGC (struct gc_thread_ *gct, lnat alloc, lnat live,
- lnat copied, nat gen,
- lnat max_copied, lnat avg_copied, lnat slop);
+void stat_endGC (Capability *cap, struct gc_thread_ *gct,
+ lnat alloc, lnat live, lnat copied, lnat slop, nat gen,
+ nat n_gc_threads, lnat par_max_copied, lnat par_tot_copied);
void stat_gcWorkerThreadStart (struct gc_thread_ *gct);
void stat_gcWorkerThreadDone (struct gc_thread_ *gct);
diff --git a/rts/Trace.c b/rts/Trace.c
index 70eb6ce506..f597726f90 100644
--- a/rts/Trace.c
+++ b/rts/Trace.c
@@ -98,6 +98,9 @@ void initTracing (void)
TRACE_gc =
RtsFlags.TraceFlags.gc ||
RtsFlags.DebugFlags.gc;
+ if (TRACE_gc && RtsFlags.GcFlags.giveStats == NO_GC_STATS) {
+ RtsFlags.GcFlags.giveStats = COLLECT_GC_STATS;
+ }
TRACE_spark_sampled =
RtsFlags.TraceFlags.sparks_sampled;
@@ -301,6 +304,44 @@ void traceGcEvent_ (Capability *cap, EventTypeNum tag)
}
}
+void traceHeapEvent_ (Capability *cap,
+ EventTypeNum tag,
+ CapsetID heap_capset,
+ lnat info1)
+{
+ /* no stderr equivalent for these ones */
+ postHeapEvent(cap, tag, heap_capset, info1);
+}
+
+void traceEventHeapInfo_ (CapsetID heap_capset,
+ nat gens,
+ lnat maxHeapSize,
+ lnat allocAreaSize,
+ lnat mblockSize,
+ lnat blockSize)
+{
+ /* no stderr equivalent for this one */
+ postEventHeapInfo(heap_capset, gens,
+ maxHeapSize, allocAreaSize,
+ mblockSize, 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)
+{
+ /* no stderr equivalent for this one */
+ postEventGcStats(cap, heap_capset, gen,
+ copied, slop, fragmentation,
+ par_n_threads, par_max_copied, par_tot_copied);
+}
+
void traceCapEvent (Capability *cap,
EventTypeNum tag)
{
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;
diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c
index 8009a38938..a43ebf789a 100644
--- a/rts/eventlog/EventLog.c
+++ b/rts/eventlog/EventLog.c
@@ -71,6 +71,11 @@ char *EventDesc[] = {
[EVENT_GC_END] = "Finished GC",
[EVENT_REQUEST_SEQ_GC] = "Request sequential GC",
[EVENT_REQUEST_PAR_GC] = "Request parallel GC",
+ [EVENT_GC_STATS_GHC] = "GC statistics",
+ [EVENT_HEAP_INFO_GHC] = "Heap static parameters",
+ [EVENT_HEAP_ALLOCATED] = "Total heap mem ever allocated",
+ [EVENT_HEAP_SIZE] = "Current heap size",
+ [EVENT_HEAP_LIVE] = "Current heap live data",
[EVENT_CREATE_SPARK_THREAD] = "Create spark thread",
[EVENT_LOG_MSG] = "Log message",
[EVENT_USER_MSG] = "User message",
@@ -358,6 +363,31 @@ initEventLogging(void)
eventTypes[t].size = 7 * sizeof(StgWord64);
break;
+ case EVENT_HEAP_ALLOCATED: // (heap_capset, alloc_bytes)
+ case EVENT_HEAP_SIZE: // (heap_capset, size_bytes)
+ case EVENT_HEAP_LIVE: // (heap_capset, live_bytes)
+ eventTypes[t].size = sizeof(EventCapsetID) + sizeof(StgWord64);
+ break;
+
+ case EVENT_HEAP_INFO_GHC: // (heap_capset, n_generations,
+ // max_heap_size, alloc_area_size,
+ // mblock_size, block_size)
+ eventTypes[t].size = sizeof(EventCapsetID)
+ + sizeof(StgWord16)
+ + sizeof(StgWord64) * 4;
+ break;
+
+ case EVENT_GC_STATS_GHC: // (heap_capset, generation,
+ // copied_bytes, slop_bytes, frag_bytes,
+ // par_n_threads,
+ // par_max_copied, par_tot_copied)
+ eventTypes[t].size = sizeof(EventCapsetID)
+ + sizeof(StgWord16)
+ + sizeof(StgWord64) * 3
+ + sizeof(StgWord32)
+ + sizeof(StgWord64) * 2;
+ break;
+
case EVENT_BLOCK_MARKER:
eventTypes[t].size = sizeof(StgWord32) + sizeof(EventTimestamp) +
sizeof(EventCapNo);
@@ -783,6 +813,101 @@ void postWallClockTime (EventCapsetID capset)
RELEASE_LOCK(&eventBufMutex);
}
+/*
+ * Various GC and heap events
+ */
+void postHeapEvent (Capability *cap,
+ EventTypeNum tag,
+ EventCapsetID heap_capset,
+ lnat info1)
+{
+ EventsBuf *eb;
+
+ eb = &capEventBuf[cap->no];
+
+ if (!hasRoomForEvent(eb, tag)) {
+ // Flush event buffer to make room for new event.
+ printAndClearEventBuf(eb);
+ }
+
+ postEventHeader(eb, tag);
+
+ switch (tag) {
+ case EVENT_HEAP_ALLOCATED: // (heap_capset, alloc_bytes)
+ case EVENT_HEAP_SIZE: // (heap_capset, size_bytes)
+ case EVENT_HEAP_LIVE: // (heap_capset, live_bytes)
+ {
+ postCapsetID(eb, heap_capset);
+ postWord64(eb,info1 /* alloc/size/live_bytes */);
+ break;
+ }
+
+ default:
+ barf("postHeapEvent: unknown event tag %d", tag);
+ }
+}
+
+void postEventHeapInfo (EventCapsetID heap_capset,
+ nat gens,
+ lnat maxHeapSize,
+ lnat allocAreaSize,
+ lnat mblockSize,
+ lnat blockSize)
+{
+ ACQUIRE_LOCK(&eventBufMutex);
+
+ if (!hasRoomForEvent(&eventBuf, EVENT_HEAP_INFO_GHC)) {
+ // Flush event buffer to make room for new event.
+ printAndClearEventBuf(&eventBuf);
+ }
+
+ postEventHeader(&eventBuf, EVENT_HEAP_INFO_GHC);
+ /* EVENT_HEAP_INFO_GHC (heap_capset, n_generations,
+ max_heap_size, alloc_area_size,
+ mblock_size, block_size) */
+ postCapsetID(&eventBuf, heap_capset);
+ postWord16(&eventBuf, gens);
+ postWord64(&eventBuf, maxHeapSize);
+ postWord64(&eventBuf, allocAreaSize);
+ postWord64(&eventBuf, mblockSize);
+ postWord64(&eventBuf, blockSize);
+
+ RELEASE_LOCK(&eventBufMutex);
+}
+
+void postEventGcStats (Capability *cap,
+ EventCapsetID heap_capset,
+ nat gen,
+ lnat copied,
+ lnat slop,
+ lnat fragmentation,
+ nat par_n_threads,
+ lnat par_max_copied,
+ lnat par_tot_copied)
+{
+ EventsBuf *eb;
+
+ eb = &capEventBuf[cap->no];
+
+ if (!hasRoomForEvent(eb, EVENT_GC_STATS_GHC)) {
+ // Flush event buffer to make room for new event.
+ printAndClearEventBuf(eb);
+ }
+
+ postEventHeader(eb, EVENT_GC_STATS_GHC);
+ /* EVENT_GC_STATS_GHC (heap_capset, generation,
+ copied_bytes, slop_bytes, frag_bytes,
+ par_n_threads, par_max_copied, par_tot_copied) */
+ postCapsetID(eb, heap_capset);
+ postWord16(eb, gen);
+ postWord64(eb, copied);
+ postWord64(eb, slop);
+ postWord64(eb, fragmentation);
+ postWord32(eb, par_n_threads);
+ postWord64(eb, par_max_copied);
+ postWord64(eb, par_tot_copied);
+}
+
void
postEvent (Capability *cap, EventTypeNum tag)
{
diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h
index 6a3b32dad3..dadc6fa6d9 100644
--- a/rts/eventlog/EventLog.h
+++ b/rts/eventlog/EventLog.h
@@ -97,6 +97,31 @@ void postThreadLabel(Capability *cap,
EventThreadID id,
char *label);
+/*
+ * Various GC and heap events
+ */
+void postHeapEvent (Capability *cap,
+ EventTypeNum tag,
+ EventCapsetID heap_capset,
+ StgWord info1);
+
+void postEventHeapInfo (EventCapsetID heap_capset,
+ nat gens,
+ lnat maxHeapSize,
+ lnat allocAreaSize,
+ lnat mblockSize,
+ lnat blockSize);
+
+void postEventGcStats (Capability *cap,
+ EventCapsetID heap_capset,
+ nat gen,
+ lnat copied,
+ lnat slop,
+ lnat fragmentation,
+ nat par_n_threads,
+ lnat par_max_copied,
+ lnat par_tot_copied);
+
#else /* !TRACING */
INLINE_HEADER void postSchedEvent (Capability *cap STG_UNUSED,
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 8201a24e5b..055a1363ed 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -738,9 +738,9 @@ GarbageCollect (rtsBool force_major_gc,
#endif
// ok, GC over: tell the stats department what happened.
- stat_endGC(gct, allocated, live_words,
- copied, N, par_max_copied, par_tot_copied,
- live_blocks * BLOCK_SIZE_W - live_words /* slop */);
+ stat_endGC(cap, gct, allocated, live_words, copied,
+ live_blocks * BLOCK_SIZE_W - live_words /* slop */,
+ N, n_gc_threads, par_max_copied, par_tot_copied);
// Guess which generation we'll collect *next* time
initialise_N(force_major_gc);
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 59ad231f34..4cd1bc99c9 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -186,6 +186,13 @@ initStorage (void)
IF_DEBUG(gc, statDescribeGens());
RELEASE_SM_LOCK;
+
+ traceEventHeapInfo(CAPSET_HEAP_DEFAULT,
+ RtsFlags.GcFlags.generations,
+ RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE_W * sizeof(W_),
+ RtsFlags.GcFlags.minAllocAreaSize * BLOCK_SIZE_W * sizeof(W_),
+ MBLOCK_SIZE_W * sizeof(W_),
+ BLOCK_SIZE_W * sizeof(W_));
}
void storageAddCapabilities (nat from, nat to)