summaryrefslogtreecommitdiff
path: root/rts/sm
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2016-04-11 19:29:14 -0700
committerSimon Marlow <marlowsd@gmail.com>2016-04-12 03:13:21 -0700
commit5c4cd0e44657d52f7ca5fee63f8765d17f1fbe85 (patch)
tree9fea4431a5a76a9e4eb27156b94781b3a697b76e /rts/sm
parent83eb4fd97a74a71e9b23b13ed656224a960fd43d (diff)
downloadhaskell-5c4cd0e44657d52f7ca5fee63f8765d17f1fbe85.tar.gz
Cache the size of part_list/scavd_list (#11783)
After a parallel GC, it is possible to have a long list of blocks in ws->part_list, if we did a lot of work stealing but didn't fill up the blocks we stole. These blocks persist until the next load-balanced GC, which might be a long time, and during every GC we were traversing this list to find its size. The fix is to maintain the size all the time, so we don't have to compute it.
Diffstat (limited to 'rts/sm')
-rw-r--r--rts/sm/GC.c7
-rw-r--r--rts/sm/GCThread.h8
-rw-r--r--rts/sm/GCUtils.c3
-rw-r--r--rts/sm/Storage.c11
4 files changed, 20 insertions, 9 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index d861db937e..02bb3bbe6b 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -820,9 +820,11 @@ new_gc_thread (nat n, gc_thread *t)
ws->part_list = NULL;
ws->n_part_blocks = 0;
+ ws->n_part_words = 0;
ws->scavd_list = NULL;
ws->n_scavd_blocks = 0;
+ ws->n_scavd_words = 0;
}
}
@@ -1219,9 +1221,11 @@ prepare_collected_gen (generation *gen)
}
ws->part_list = NULL;
ws->n_part_blocks = 0;
+ ws->n_part_words = 0;
ASSERT(ws->scavd_list == NULL);
ASSERT(ws->n_scavd_blocks == 0);
+ ASSERT(ws->n_scavd_words == 0);
if (ws->todo_free != ws->todo_bd->start) {
ws->todo_bd->free = ws->todo_free;
@@ -1346,7 +1350,6 @@ collect_gct_blocks (void)
prev = NULL;
for (bd = ws->scavd_list; bd != NULL; bd = bd->link) {
- ws->gen->n_words += bd->free - bd->start;
prev = bd;
}
if (prev != NULL) {
@@ -1354,9 +1357,11 @@ collect_gct_blocks (void)
ws->gen->blocks = ws->scavd_list;
}
ws->gen->n_blocks += ws->n_scavd_blocks;
+ ws->gen->n_words += ws->n_scavd_words;
ws->scavd_list = NULL;
ws->n_scavd_blocks = 0;
+ ws->n_scavd_words = 0;
RELEASE_SPIN_LOCK(&ws->gen->sync);
}
diff --git a/rts/sm/GCThread.h b/rts/sm/GCThread.h
index ca90717b81..1fee7a68e9 100644
--- a/rts/sm/GCThread.h
+++ b/rts/sm/GCThread.h
@@ -94,13 +94,15 @@ typedef struct gen_workspace_ {
// Objects that have already been scavenged.
bdescr * scavd_list;
- nat n_scavd_blocks; // count of blocks in this list
+ StgWord n_scavd_blocks; // count of blocks in this list
+ StgWord n_scavd_words;
// Partially-full, scavenged, blocks
bdescr * part_list;
- unsigned int n_part_blocks; // count of above
+ StgWord n_part_blocks; // count of above
+ StgWord n_part_words;
- StgWord pad[3];
+ StgWord pad[1];
} gen_workspace ATTRIBUTE_ALIGNED(64);
// align so that computing gct->gens[n] is a shift, not a multiply
diff --git a/rts/sm/GCUtils.c b/rts/sm/GCUtils.c
index 1c6a93c3b2..364a10a759 100644
--- a/rts/sm/GCUtils.c
+++ b/rts/sm/GCUtils.c
@@ -146,6 +146,7 @@ push_scanned_block (bdescr *bd, gen_workspace *ws)
bd->link = ws->part_list;
ws->part_list = bd;
ws->n_part_blocks += bd->blocks;
+ ws->n_part_words += bd->free - bd->start;
IF_DEBUG(sanity,
ASSERT(countBlocks(ws->part_list) == ws->n_part_blocks));
}
@@ -155,6 +156,7 @@ push_scanned_block (bdescr *bd, gen_workspace *ws)
bd->link = ws->scavd_list;
ws->scavd_list = bd;
ws->n_scavd_blocks += bd->blocks;
+ ws->n_scavd_words += bd->free - bd->start;
IF_DEBUG(sanity,
ASSERT(countBlocks(ws->scavd_list) == ws->n_scavd_blocks));
}
@@ -306,6 +308,7 @@ alloc_todo_block (gen_workspace *ws, nat size)
{
ws->part_list = bd->link;
ws->n_part_blocks -= bd->blocks;
+ ws->n_part_words -= bd->free - bd->start;
}
else
{
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 45bb54ca65..18ae796864 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -1183,13 +1183,14 @@ W_ genLiveBlocks (generation *gen)
W_ gcThreadLiveWords (nat i, nat g)
{
- W_ words;
+ W_ a, b, c;
- words = countOccupied(gc_threads[i]->gens[g].todo_bd);
- words += countOccupied(gc_threads[i]->gens[g].part_list);
- words += countOccupied(gc_threads[i]->gens[g].scavd_list);
+ a = countOccupied(gc_threads[i]->gens[g].todo_bd);
+ b = gc_threads[i]->gens[g].n_part_words;
+ c = gc_threads[i]->gens[g].n_scavd_words;
- return words;
+// debugBelch("cap %d, g%d, %ld %ld %ld\n", i, g, a, b, c);
+ return a + b + c;
}
W_ gcThreadLiveBlocks (nat i, nat g)