[commit: ghc] local-gc: merge commit cc2ea98ac4a15e40a15e89de9e47f33e191ba393 (b044b6f)
Simon Marlow
marlowsd at gmail.com
Mon Jun 6 05:57:16 CEST 2011
Repository : ssh://darcs.haskell.org//srv/darcs/ghc
On branch : local-gc
http://hackage.haskell.org/trac/ghc/changeset/b044b6f4d33a465a90320bb7d36e85a6885110d1
>---------------------------------------------------------------
commit b044b6f4d33a465a90320bb7d36e85a6885110d1
Merge: 9c9d1fd... cc2ea98...
Author: Simon Marlow <marlowsd at gmail.com>
Date: Sun Jun 5 16:04:22 2011 +0100
merge commit cc2ea98ac4a15e40a15e89de9e47f33e191ba393
HACKING | 7 ++++++-
aclocal.m4 | 10 +++-------
compiler/cmm/CmmExpr.hs | 6 ++++--
compiler/cmm/OptimizationFuel.hs | 14 --------------
compiler/codeGen/CodeGen.lhs | 2 +-
compiler/codeGen/StgCmm.hs | 3 ++-
compiler/utils/GraphOps.hs | 15 ++++++++-------
compiler/utils/UniqFM.lhs | 23 ++++++++++++++++++++++-
rts/Stats.c | 7 +++++++
rts/sm/GC.c | 7 -------
rts/sm/Sanity.c | 4 ++++
rts/sm/Storage.c | 27 +++++++++++++++++++++------
12 files changed, 78 insertions(+), 47 deletions(-)
diff --cc rts/Stats.c
index 1162d2b,3e7b5d8..bfb82c4
--- a/rts/Stats.c
+++ b/rts/Stats.c
@@@ -887,42 -795,34 +887,49 @@@ statDescribeGens(void
gen_live = genLiveWords(gen);
gen_blocks = genLiveBlocks(gen);
- mut = 0;
+ slop = gen_blocks * BLOCK_SIZE_W - gen_live;
+
+ debugBelch("%5d %7d %8d %8d %4s %8s %8d %8ld %8ld\n",
+ g, gen->max_blocks, lge, gen->n_prim_blocks, "", "", gen_blocks,
+ gen_live*sizeof(W_), slop*sizeof(W_));
+
for (i = 0; i < n_capabilities; i++) {
- mut += countOccupied(capabilities[i].mut_lists[g]);
+ cap_mut = countOccupied(capabilities[i].mut_lists[g]);
+
+ cap_live = gcThreadLiveWords(i,n);
+ cap_blocks = gcThreadLiveBlocks(i,n);
+
+ slop = cap_blocks * BLOCK_SIZE_W - cap_live;
+
+ debugBelch("%5s %7s %8s %8s %4d %8ld %8d %8ld %8ld\n",
+ "", "", "", "", i, cap_mut*sizeof(W_), cap_blocks,
+ cap_live*sizeof(W_), slop*sizeof(W_));
+ // Add the pinned object block.
+ bd = capabilities[i].pinned_object_block;
+ if (bd != NULL) {
+ gen_live += bd->free - bd->start;
+ gen_blocks += bd->blocks;
+ }
+
- gen_live += gcThreadLiveWords(i,g);
- gen_live += gcThreadLiveWords(i,g);
- gen_blocks += gcThreadLiveBlocks(i,g);
- }
+ gen_mut += cap_mut;
+ gen_live += cap_live;
+ gen_blocks += cap_blocks;
+ }
- debugBelch("%5d %7d %9d", g, gen->max_blocks, mut);
+ debugBelch("%55s-----------------\n","");
+ debugBelch("%5s %7s %8s %4s %8s %8s %8s %8ld %8ld\n\n",
+ "", "", "", "", "", "", "",
+ gen_live*sizeof(W_), slop*sizeof(W_));
- gen_slop = gen_blocks * BLOCK_SIZE_W - gen_live;
+ slop = gen_blocks * BLOCK_SIZE_W - gen_live;
- debugBelch("%8ld %8d %8ld %8ld\n", gen_blocks, lge,
- gen_live*sizeof(W_), gen_slop*sizeof(W_));
tot_live += gen_live;
- tot_slop += gen_slop;
+ tot_slop += slop;
}
- debugBelch("----------------------------------------------------------\n");
- debugBelch("%41s%8ld %8ld\n","",tot_live*sizeof(W_),tot_slop*sizeof(W_));
- debugBelch("----------------------------------------------------------\n");
+ debugBelch("------------------------------------------------------------------------\n");
+ debugBelch("%55s%8ld %8ld\n","",tot_live*sizeof(W_),tot_slop*sizeof(W_));
+ debugBelch("------------------------------------------------------------------------\n");
debugBelch("\n");
}
diff --cc rts/sm/GC.c
index ba4aab2,3036140..3375760
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@@ -658,25 -597,18 +658,18 @@@ GarbageCollect (nat N, // generation t
// update the max size of older generations after a major GC
resize_generations();
- // Start a new pinned_object_block
- if (gc_type == GC_LOCAL) {
- cap->pinned_object_block = NULL;
- } else {
- for (n = 0; n < n_capabilities; n++) {
- capabilities[n].pinned_object_block = NULL;
- }
- // Free the mark stack.
- if (mark_stack_top_bd != NULL) {
- debugTrace(DEBUG_gc, "mark stack: %d blocks",
- countBlocks(mark_stack_top_bd));
- freeChain(mark_stack_top_bd);
}
+ // Free the mark stack, leaving one block.
+ freeMarkStack();
+
// Free any bitmaps.
- for (g = 0; g <= N; g++) {
- gen = &generations[g];
+ for (g = 0; g < total_generations; g++) {
+ gen = &all_generations[g];
+ if (gct->gc_type == GC_LOCAL && isNonLocalGen(gen))
+ continue;
if (gen->bitmap != NULL) {
- freeGroup(gen->bitmap);
+ freeGroup_sync(gen->bitmap);
gen->bitmap = NULL;
}
}
diff --cc rts/sm/Sanity.c
index 8c82d47,0ec552c..623831a
--- a/rts/sm/Sanity.c
+++ b/rts/sm/Sanity.c
@@@ -1109,7 -789,7 +1109,8 @@@ findMemoryLeak (void
for (i = 0; i < n_capabilities; i++) {
markBlocks(nurseries[i].blocks);
+ markBlocks(gc_threads[i]->mark_stack_top_bd);
+ markBlocks(capabilities[i].pinned_object_block);
}
#ifdef PROFILING
@@@ -1205,13 -881,11 +1206,16 @@@ memInventory (rtsBool show
for (i = 0; i < n_capabilities; i++) {
ASSERT(countBlocks(nurseries[i].blocks) == nurseries[i].n_blocks);
nursery_blocks += nurseries[i].n_blocks;
+ if (capabilities[i].pinned_object_block != NULL) {
+ nursery_blocks += capabilities[i].pinned_object_block->blocks;
+ }
}
+ mark_stack_blocks = 0;
+ for (i = 0; i < n_capabilities; i++) {
+ mark_stack_blocks += countBlocks(gc_threads[i]->mark_stack_top_bd);
+ }
+
retainer_blocks = 0;
#ifdef PROFILING
if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
diff --cc rts/sm/Storage.c
index 1920a3c,f8a9e55..4cb22f5
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@@ -765,18 -657,32 +765,33 @@@ allocatePinned (Capability *cap, lnat n
// If we don't have a block of pinned objects yet, or the current
// one isn't large enough to hold the new object, allocate a new one.
if (bd == NULL || (bd->free + n) > (bd->start + BLOCK_SIZE_W)) {
+ // The pinned_object_block remains attached to the capability
+ // until it is full, even if a GC occurs. We want this
+ // behaviour because otherwise the unallocated portion of the
+ // block would be forever slop, and under certain workloads
+ // (allocating a few ByteStrings per GC) we accumulate a lot
+ // of slop.
+ //
+ // So, the pinned_object_block is initially marked
+ // BF_EVACUATED so the GC won't touch it. When it is full,
+ // we place it on the large_objects list, and at the start of
+ // the next GC the BF_EVACUATED flag will be cleared, and the
+ // block will be promoted as usual (if anything in it is
+ // live).
ACQUIRE_SM_LOCK;
- cap->pinned_object_block = bd = allocBlock();
+ gen = cap->r.rG0; // use our local G0
- dbl_link_onto(bd, &gen->large_objects);
- gen->n_large_blocks++;
+ if (bd != NULL) {
- dbl_link_onto(bd, &g0->large_objects);
- g0->n_large_blocks++;
++ dbl_link_onto(bd, &gen->large_objects);
++ gen->n_large_blocks++;
+ g0->n_new_large_words += bd->free - bd->start;
+ }
+ cap->pinned_object_block = bd = allocBlock();
RELEASE_SM_LOCK;
- initBdescr(bd, g0, g0);
+ initBdescr(bd, gen, gen);
- bd->flags = BF_PINNED | BF_LARGE;
- bd->free = bd->start;
+ bd->flags = BF_PINNED | BF_LARGE | BF_EVACUATED;
- bd->free = bd->start;
++ bd->free = bd->start;
}
- cap->r.rG0->n_new_large_words += n;
p = bd->free;
bd->free += n;
return p;
More information about the Cvs-ghc
mailing list