From 74ee9df9f9e79e7110e9d8541b84010f35c464c5 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Mon, 9 Jun 2008 17:49:43 +0000 Subject: Experimental "mark-region" strategy for the old generation Sometimes better than the default copying, enabled by +RTS -w --- rts/sm/Sweep.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 rts/sm/Sweep.c (limited to 'rts/sm/Sweep.c') 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); +} -- cgit v1.2.1