Commit 6db4be95 authored by Ben Gamari's avatar Ben Gamari 🐢 Committed by Ben Gamari

rts: Tracing support for nonmoving collection events

This introduces a few events to mark key points in the nonmoving
garbage collection cycle. These include:

 * `EVENT_CONC_MARK_BEGIN`, denoting the beginning of a round of
   marking. This may happen more than once in a single major collection
   since we the major collector iterates until it hits a fixed point.

 * `EVENT_CONC_MARK_END`, denoting the end of a round of marking.

 * `EVENT_CONC_SYNC_BEGIN`, denoting the beginning of the post-mark
   synchronization phase

 * `EVENT_CONC_UPD_REM_SET_FLUSH`, indicating that a capability has
   flushed its update remembered set.

 * `EVENT_CONC_SYNC_END`, denoting that all mutators have flushed their
   update remembered sets.

 * `EVENT_CONC_SWEEP_BEGIN`, denoting the beginning of the sweep portion
   of the major collection.

 * `EVENT_CONC_SWEEP_END`, denoting the end of the sweep portion of the
   major collection.
parent 431e9bf4
......@@ -183,12 +183,20 @@
#define EVENT_USER_BINARY_MSG 181
#define EVENT_CONC_MARK_BEGIN 200
#define EVENT_CONC_MARK_END 201
#define EVENT_CONC_SYNC_BEGIN 202
#define EVENT_CONC_SYNC_END 203
#define EVENT_CONC_SWEEP_BEGIN 204
#define EVENT_CONC_SWEEP_END 205
#define EVENT_CONC_UPD_REM_SET_FLUSH 206
/*
* The highest event code +1 that ghc itself emits. Note that some event
* 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 182
#define NUM_GHC_EVENT_TAGS 207
#if 0 /* DEPRECATED EVENTS: */
/* we don't actually need to record the thread, it's implicit */
......
......@@ -802,6 +802,49 @@ void traceThreadLabel_(Capability *cap,
}
}
void traceConcMarkBegin()
{
if (eventlog_enabled)
postEventNoCap(EVENT_CONC_MARK_BEGIN);
}
void traceConcMarkEnd(StgWord32 marked_obj_count)
{
if (eventlog_enabled)
postConcMarkEnd(marked_obj_count);
}
void traceConcSyncBegin()
{
if (eventlog_enabled)
postEventNoCap(EVENT_CONC_SYNC_BEGIN);
}
void traceConcSyncEnd()
{
if (eventlog_enabled)
postEventNoCap(EVENT_CONC_SYNC_END);
}
void traceConcSweepBegin()
{
if (eventlog_enabled)
postEventNoCap(EVENT_CONC_SWEEP_BEGIN);
}
void traceConcSweepEnd()
{
if (eventlog_enabled)
postEventNoCap(EVENT_CONC_SWEEP_END);
}
void traceConcUpdRemSetFlush(Capability *cap)
{
if (eventlog_enabled)
postConcUpdRemSetFlush(cap);
}
void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
{
#if defined(DEBUG)
......
......@@ -304,6 +304,14 @@ void traceHeapProfSampleCostCentre(StgWord8 profile_id,
CostCentreStack *stack, StgWord residency);
#endif /* PROFILING */
void traceConcMarkBegin(void);
void traceConcMarkEnd(StgWord32 marked_obj_count);
void traceConcSyncBegin(void);
void traceConcSyncEnd(void);
void traceConcSweepBegin(void);
void traceConcSweepEnd(void);
void traceConcUpdRemSetFlush(Capability *cap);
void flushTrace(void);
#else /* !TRACING */
......@@ -344,6 +352,14 @@ void flushTrace(void);
#define traceHeapProfSampleCostCentre(profile_id, stack, residency) /* nothing */
#define traceHeapProfSampleString(profile_id, label, residency) /* nothing */
#define traceConcMarkBegin() /* nothing */
#define traceConcMarkEnd(marked_obj_count) /* nothing */
#define traceConcSyncBegin() /* nothing */
#define traceConcSyncEnd() /* nothing */
#define traceConcSweepBegin() /* nothing */
#define traceConcSweepEnd() /* nothing */
#define traceConcUpdRemSetFlush(cap) /* nothing */
#define flushTrace() /* nothing */
#endif /* TRACING */
......
......@@ -107,7 +107,14 @@ char *EventDesc[] = {
[EVENT_HEAP_PROF_SAMPLE_END] = "End of heap profile sample",
[EVENT_HEAP_PROF_SAMPLE_STRING] = "Heap profile string sample",
[EVENT_HEAP_PROF_SAMPLE_COST_CENTRE] = "Heap profile cost-centre sample",
[EVENT_USER_BINARY_MSG] = "User binary message"
[EVENT_USER_BINARY_MSG] = "User binary message",
[EVENT_CONC_MARK_BEGIN] = "Begin concurrent mark phase",
[EVENT_CONC_MARK_END] = "End concurrent mark phase",
[EVENT_CONC_SYNC_BEGIN] = "Begin concurrent GC synchronisation",
[EVENT_CONC_SYNC_END] = "End concurrent GC synchronisation",
[EVENT_CONC_SWEEP_BEGIN] = "Begin concurrent sweep",
[EVENT_CONC_SWEEP_END] = "End concurrent sweep",
[EVENT_CONC_UPD_REM_SET_FLUSH] = "Update remembered set flushed"
};
// Event type.
......@@ -446,6 +453,23 @@ init_event_types(void)
eventTypes[t].size = EVENT_SIZE_DYNAMIC;
break;
case EVENT_CONC_MARK_BEGIN:
case EVENT_CONC_SYNC_BEGIN:
case EVENT_CONC_SYNC_END:
case EVENT_CONC_SWEEP_BEGIN:
case EVENT_CONC_SWEEP_END:
eventTypes[t].size = 0;
break;
case EVENT_CONC_MARK_END:
eventTypes[t].size = 4;
break;
case EVENT_CONC_UPD_REM_SET_FLUSH: // (cap)
eventTypes[t].size =
sizeof(EventCapNo);
break;
default:
continue; /* ignore deprecated events */
}
......@@ -1004,6 +1028,15 @@ void postTaskDeleteEvent (EventTaskId taskId)
RELEASE_LOCK(&eventBufMutex);
}
void
postEventNoCap (EventTypeNum tag)
{
ACQUIRE_LOCK(&eventBufMutex);
ensureRoomForEvent(&eventBuf, tag);
postEventHeader(&eventBuf, tag);
RELEASE_LOCK(&eventBufMutex);
}
void
postEvent (Capability *cap, EventTypeNum tag)
{
......@@ -1130,6 +1163,23 @@ void postThreadLabel(Capability *cap,
postBuf(eb, (StgWord8*) label, strsize);
}
void postConcUpdRemSetFlush(Capability *cap)
{
EventsBuf *eb = &capEventBuf[cap->no];
ensureRoomForEvent(eb, EVENT_CONC_UPD_REM_SET_FLUSH);
postEventHeader(eb, EVENT_CONC_UPD_REM_SET_FLUSH);
postCapNo(eb, cap->no);
}
void postConcMarkEnd(StgWord32 marked_obj_count)
{
ACQUIRE_LOCK(&eventBufMutex);
ensureRoomForEvent(&eventBuf, EVENT_CONC_MARK_END);
postEventHeader(&eventBuf, EVENT_CONC_MARK_END);
postWord32(&eventBuf, marked_obj_count);
RELEASE_LOCK(&eventBufMutex);
}
void closeBlockMarker (EventsBuf *ebuf)
{
if (ebuf->marker)
......
......@@ -39,6 +39,7 @@ void postSchedEvent(Capability *cap, EventTypeNum tag,
* Post a nullary event.
*/
void postEvent(Capability *cap, EventTypeNum tag);
void postEventNoCap(EventTypeNum tag);
void postEventAtTimestamp (Capability *cap, EventTimestamp ts,
EventTypeNum tag);
......@@ -159,6 +160,9 @@ void postHeapProfSampleCostCentre(StgWord8 profile_id,
StgWord64 residency);
#endif /* PROFILING */
void postConcUpdRemSetFlush(Capability *cap);
void postConcMarkEnd(StgWord32 marked_obj_count);
#else /* !TRACING */
INLINE_HEADER void postSchedEvent (Capability *cap STG_UNUSED,
......@@ -172,6 +176,9 @@ INLINE_HEADER void postEvent (Capability *cap STG_UNUSED,
EventTypeNum tag STG_UNUSED)
{ /* nothing */ }
INLINE_HEADER void postEventNoCap (EventTypeNum tag STG_UNUSED)
{ /* nothing */ }
INLINE_HEADER void postMsg (char *msg STG_UNUSED,
va_list ap STG_UNUSED)
{ /* nothing */ }
......
......@@ -735,6 +735,8 @@ static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO *
* Sweep
****************************************************/
traceConcSweepBegin();
// Because we can't mark large object blocks (no room for mark bit) we
// collect them in a map in mark_queue and we pass it here to sweep large
// objects
......@@ -744,6 +746,7 @@ static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO *
nonmovingSweep();
ASSERT(nonmovingHeap.sweep_list == NULL);
debugTrace(DEBUG_nonmoving_gc, "Finished sweeping.");
traceConcSweepEnd();
// TODO: Remainder of things done by GarbageCollect (update stats)
......
......@@ -238,6 +238,7 @@ void nonmovingFlushCapUpdRemSetBlocks(Capability *cap)
debugTrace(DEBUG_nonmoving_gc,
"Capability %d flushing update remembered set: %d",
cap->no, markQueueLength(&cap->upd_rem_set.queue));
traceConcUpdRemSetFlush(cap);
nonmovingAddUpdRemSetBlocks(&cap->upd_rem_set.queue);
atomic_inc(&upd_rem_set_flush_count, 1);
signalCondition(&upd_rem_set_flushed_cond);
......@@ -251,6 +252,7 @@ void nonmovingFlushCapUpdRemSetBlocks(Capability *cap)
void nonmovingBeginFlush(Task *task)
{
debugTrace(DEBUG_nonmoving_gc, "Starting update remembered set flush...");
traceConcSyncBegin();
upd_rem_set_flush_count = 0;
stopAllCapabilitiesWith(NULL, task, SYNC_FLUSH_UPD_REM_SET);
......@@ -342,6 +344,7 @@ void nonmovingFinishFlush(Task *task)
upd_rem_set_block_list = NULL;
debugTrace(DEBUG_nonmoving_gc, "Finished update remembered set flush...");
traceConcSyncEnd();
releaseAllCapabilities(n_capabilities, NULL, task);
}
#endif
......@@ -1434,6 +1437,7 @@ mark_closure (MarkQueue *queue, StgClosure *p, StgClosure **origin)
GNUC_ATTR_HOT void
nonmovingMark (MarkQueue *queue)
{
traceConcMarkBegin();
debugTrace(DEBUG_nonmoving_gc, "Starting mark pass");
unsigned int count = 0;
while (true) {
......@@ -1474,6 +1478,7 @@ nonmovingMark (MarkQueue *queue)
} else {
// Nothing more to do
debugTrace(DEBUG_nonmoving_gc, "Finished mark pass: %d", count);
traceConcMarkEnd(count);
return;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment