summaryrefslogtreecommitdiff
path: root/rts/sm/Sweep.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2008-06-09 17:49:43 +0000
committerSimon Marlow <marlowsd@gmail.com>2008-06-09 17:49:43 +0000
commit74ee9df9f9e79e7110e9d8541b84010f35c464c5 (patch)
treea7a10946773a1f12d367c063e4ac343e6580d9ad /rts/sm/Sweep.c
parent54fe7a440247fbd0f853d07da23d48b50a229a00 (diff)
downloadhaskell-74ee9df9f9e79e7110e9d8541b84010f35c464c5.tar.gz
Experimental "mark-region" strategy for the old generation
Sometimes better than the default copying, enabled by +RTS -w
Diffstat (limited to 'rts/sm/Sweep.c')
-rw-r--r--rts/sm/Sweep.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/rts/sm/Sweep.c b/rts/sm/Sweep.c
new file mode 100644
index 0000000000..979fe9ccea
--- /dev/null
+++ b/rts/sm/Sweep.c
@@ -0,0 +1,82 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team 2008
+ *
+ * Simple mark/sweep, collecting whole blocks.
+ *
+ * Documentation on the architecture of the Garbage Collector can be
+ * found in the online commentary:
+ *
+ * http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "Rts.h"
+#include "Sweep.h"
+#include "Block.h"
+#include "Trace.h"
+
+void
+sweep(step *step)
+{
+ bdescr *bd, *prev, *next;
+ nat i;
+ nat freed, resid, fragd, blocks, live;
+
+ ASSERT(countBlocks(step->old_blocks) == step->n_old_blocks);
+
+ live = 0; // estimate of live data in this gen
+ freed = 0;
+ fragd = 0;
+ blocks = 0;
+ prev = NULL;
+ for (bd = step->old_blocks; bd != NULL; bd = next)
+ {
+ next = bd->link;
+
+ if (!(bd->flags & BF_MARKED)) {
+ prev = bd;
+ continue;
+ }
+
+ blocks++;
+ resid = 0;
+ for (i = 0; i < BLOCK_SIZE_W / BITS_IN(W_); i++)
+ {
+ if (bd->u.bitmap[i] != 0) resid++;
+ }
+ live += resid * BITS_IN(W_);
+
+ if (resid == 0)
+ {
+ freed++;
+ step->n_old_blocks--;
+ if (prev == NULL) {
+ step->old_blocks = next;
+ } else {
+ prev->link = next;
+ }
+ freeGroup(bd);
+ }
+ else
+ {
+ prev = bd;
+ if (resid < (BLOCK_SIZE_W * 3) / (BITS_IN(W_) * 4)) {
+ fragd++;
+ bd->flags |= BF_FRAGMENTED;
+ }
+ }
+ }
+
+ step->live_estimate = live;
+
+ trace(DEBUG_gc|TRACE_gc, "sweeping: %d blocks, %d were copied, %d freed (%d%%), %d are fragmented, live estimate: %d%%",
+ step->n_old_blocks + freed,
+ step->n_old_blocks - blocks + freed,
+ freed,
+ blocks == 0 ? 0 : (freed * 100) / blocks,
+ fragd,
+ (blocks - freed) == 0 ? 0 : ((live / BLOCK_SIZE_W) * 100) / (blocks - freed));
+
+ ASSERT(countBlocks(step->old_blocks) == step->n_old_blocks);
+}