diff options
author | Simon Marlow <marlowsd@gmail.com> | 2008-06-09 17:49:43 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2008-06-09 17:49:43 +0000 |
commit | 74ee9df9f9e79e7110e9d8541b84010f35c464c5 (patch) | |
tree | a7a10946773a1f12d367c063e4ac343e6580d9ad /rts/sm/Sweep.c | |
parent | 54fe7a440247fbd0f853d07da23d48b50a229a00 (diff) | |
download | haskell-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.c | 82 |
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); +} |