summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-09-30 23:21:31 +0000
committerBen Gamari <ben@smart-cactus.org>2020-10-24 21:00:57 -0400
commitd0d07cffeded2b1d1b4ffed1f8b06eddc9f06600 (patch)
tree1bbbd9e9d5b5466dbe458950f95297885e56531b
parent1f4cbc2942ad8b757a225b23c9f097f371ca490c (diff)
downloadhaskell-d0d07cffeded2b1d1b4ffed1f8b06eddc9f06600.tar.gz
rts: Rework handling of mutlist scavenging statistics
-rw-r--r--rts/sm/GC.c61
-rw-r--r--rts/sm/GC.h28
-rw-r--r--rts/sm/Scav.c31
3 files changed, 83 insertions, 37 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 0fa927f2ad..3d4a151cd5 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -112,14 +112,8 @@ static W_ g0_pcnt_kept = 30; // percentage of g0 live at last minor GC
/* Mut-list stats */
#if defined(DEBUG)
-uint32_t mutlist_MUTVARS,
- mutlist_MUTARRS,
- mutlist_MVARS,
- mutlist_TVAR,
- mutlist_TVAR_WATCH_QUEUE,
- mutlist_TREC_CHUNK,
- mutlist_TREC_HEADER,
- mutlist_OTHERS;
+// For lack of a better option we protect mutlist_scav_stats with oldest_gen->sync
+MutListScavStats mutlist_scav_stats;
#endif
/* Thread-local data for each GC thread
@@ -184,6 +178,36 @@ bdescr *mark_stack_top_bd; // topmost block in the mark stack
bdescr *mark_stack_bd; // current block in the mark stack
StgPtr mark_sp; // pointer to the next unallocated mark stack entry
+
+/* -----------------------------------------------------------------------------
+ Statistics from mut_list scavenging
+ -------------------------------------------------------------------------- */
+
+#if defined(DEBUG)
+void
+zeroMutListScavStats(MutListScavStats *src)
+{
+ memset(src, 0, sizeof(MutListScavStats));
+}
+
+void
+addMutListScavStats(const MutListScavStats *src,
+ MutListScavStats *dest)
+{
+#define ADD_STATS(field) dest->field += src->field;
+ ADD_STATS(n_MUTVAR);
+ ADD_STATS(n_MUTARR);
+ ADD_STATS(n_MVAR);
+ ADD_STATS(n_TVAR);
+ ADD_STATS(n_TREC_CHUNK);
+ ADD_STATS(n_TVAR_WATCH_QUEUE);
+ ADD_STATS(n_TREC_HEADER);
+ ADD_STATS(n_OTHERS);
+#undef ADD_STATS
+}
+#endif /* DEBUG */
+
+
/* -----------------------------------------------------------------------------
GarbageCollect: the main entry point to the garbage collector.
@@ -250,14 +274,7 @@ GarbageCollect (uint32_t collect_gen,
stablePtrLock();
#if defined(DEBUG)
- mutlist_MUTVARS = 0;
- mutlist_MUTARRS = 0;
- mutlist_MVARS = 0;
- mutlist_TVAR = 0;
- mutlist_TVAR_WATCH_QUEUE = 0;
- mutlist_TREC_CHUNK = 0;
- mutlist_TREC_HEADER = 0;
- mutlist_OTHERS = 0;
+ zeroMutListScavStats(&mutlist_scav_stats);
#endif
// attribute any costs to CCS_GC
@@ -590,10 +607,14 @@ GarbageCollect (uint32_t collect_gen,
debugTrace(DEBUG_gc,
"mut_list_size: %lu (%d vars, %d arrays, %d MVARs, %d TVARs, %d TVAR_WATCH_QUEUEs, %d TREC_CHUNKs, %d TREC_HEADERs, %d others)",
(unsigned long)(mut_list_size * sizeof(W_)),
- mutlist_MUTVARS, mutlist_MUTARRS, mutlist_MVARS,
- mutlist_TVAR, mutlist_TVAR_WATCH_QUEUE,
- mutlist_TREC_CHUNK, mutlist_TREC_HEADER,
- mutlist_OTHERS);
+ mutlist_scav_stats.n_MUTVAR,
+ mutlist_scav_stats.n_MUTARR,
+ mutlist_scav_stats.n_MVAR,
+ mutlist_scav_stats.n_TVAR,
+ mutlist_scav_stats.n_TVAR_WATCH_QUEUE,
+ mutlist_scav_stats.n_TREC_CHUNK,
+ mutlist_scav_stats.n_TREC_HEADER,
+ mutlist_scav_stats.n_OTHERS);
}
bdescr *next, *prev;
diff --git a/rts/sm/GC.h b/rts/sm/GC.h
index bde006913b..c5d5f6ac81 100644
--- a/rts/sm/GC.h
+++ b/rts/sm/GC.h
@@ -42,20 +42,32 @@ extern StgPtr mark_sp;
extern bool work_stealing;
-#if defined(DEBUG)
-extern uint32_t mutlist_MUTVARS, mutlist_MUTARRS, mutlist_MVARS, mutlist_OTHERS,
- mutlist_TVAR,
- mutlist_TVAR_WATCH_QUEUE,
- mutlist_TREC_CHUNK,
- mutlist_TREC_HEADER;
-#endif
-
#if defined(PROF_SPIN) && defined(THREADED_RTS)
extern volatile StgWord64 whitehole_gc_spin;
extern volatile StgWord64 waitForGcThreads_spin;
extern volatile StgWord64 waitForGcThreads_yield;
#endif
+// mutable list scavenging statistics
+#if defined(DEBUG)
+typedef struct {
+ StgWord n_MUTVAR;
+ StgWord n_MUTARR;
+ StgWord n_MVAR;
+ StgWord n_TVAR;
+ StgWord n_TREC_CHUNK;
+ StgWord n_TVAR_WATCH_QUEUE;
+ StgWord n_TREC_HEADER;
+ StgWord n_OTHERS;
+} MutListScavStats;
+
+extern MutListScavStats mutlist_scav_stats;
+
+void zeroMutListScavStats(MutListScavStats *src);
+void addMutListScavStats(const MutListScavStats *src,
+ MutListScavStats *dest);
+#endif /* DEBUG */
+
void gcWorkerThread (Capability *cap);
void initGcThreads (uint32_t from, uint32_t to);
void freeGcThreads (void);
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index dd9a96adf8..0a4e76a819 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -65,6 +65,8 @@
#include "sm/NonMoving.h" // for nonmoving_set_closure_mark_bit
#include "sm/NonMovingScav.h"
+#include <string.h> /* for memset */
+
static void scavenge_large_bitmap (StgPtr p,
StgLargeBitmap *large_bitmap,
StgWord size );
@@ -1583,6 +1585,10 @@ static void
scavenge_mutable_list(bdescr *bd, generation *gen)
{
StgPtr p, q;
+#if defined(DEBUG)
+ MutListScavStats stats; // Local accumulator
+ zeroMutListScavStats(&stats);
+#endif
uint32_t gen_no = gen->no;
gct->evac_gen_no = gen_no;
@@ -1598,31 +1604,31 @@ scavenge_mutable_list(bdescr *bd, generation *gen)
case MUT_VAR_CLEAN:
// can happen due to concurrent writeMutVars
case MUT_VAR_DIRTY:
- mutlist_MUTVARS++; break;
+ stats.n_MUTVAR++; break;
case MUT_ARR_PTRS_CLEAN:
case MUT_ARR_PTRS_DIRTY:
case MUT_ARR_PTRS_FROZEN_CLEAN:
case MUT_ARR_PTRS_FROZEN_DIRTY:
- mutlist_MUTARRS++; break;
+ stats.n_MUTARR++; break;
case MVAR_CLEAN:
barf("MVAR_CLEAN on mutable list");
case MVAR_DIRTY:
- mutlist_MVARS++; break;
+ stats.n_MVAR++; break;
case TVAR:
- mutlist_TVAR++; break;
+ stats.n_TVAR++; break;
case TREC_CHUNK:
- mutlist_TREC_CHUNK++; break;
+ stats.n_TREC_CHUNK++; break;
case MUT_PRIM:
pinfo = ((StgClosure*)p)->header.info;
if (pinfo == &stg_TVAR_WATCH_QUEUE_info)
- mutlist_TVAR_WATCH_QUEUE++;
+ stats.n_TVAR_WATCH_QUEUE++;
else if (pinfo == &stg_TREC_HEADER_info)
- mutlist_TREC_HEADER++;
+ stats.n_TREC_HEADER++;
else
- mutlist_OTHERS++;
+ stats.n_OTHERS++;
break;
default:
- mutlist_OTHERS++; break;
+ stats.n_OTHERS++; break;
}
#endif
@@ -1671,6 +1677,13 @@ scavenge_mutable_list(bdescr *bd, generation *gen)
}
}
}
+
+#if defined(DEBUG)
+ // For lack of a better option we protect mutlist_scav_stats with oldest_gen->sync
+ ACQUIRE_SPIN_LOCK(&oldest_gen->sync);
+ addMutListScavStats(&stats, &mutlist_scav_stats);
+ RELEASE_SPIN_LOCK(&oldest_gen->sync);
+#endif
}
void