summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2012-09-21 13:18:49 +0100
committerSimon Marlow <marlowsd@gmail.com>2012-09-21 13:46:47 +0100
commit016fd74d6517512b62b36ff12cdccf2e723a0fb3 (patch)
treef5be8ca85dc2651ca63932b064f04baf9b7fe01f
parent1f5d83648dfda39d999eb8a9e8192339b3eea540 (diff)
downloadhaskell-016fd74d6517512b62b36ff12cdccf2e723a0fb3.tar.gz
Cache the result of countOccupied(gen->large_objects) as gen->n_large_words (#7257)
The program in #7257 was spending 90% of its time counting the live data in gen->large_objects. We already avoid doing this for small objects, but in this example the old generation was full of large objects (actually pinned ByteStrings).
-rw-r--r--includes/rts/storage/GC.h1
-rw-r--r--rts/sm/GC.c5
-rw-r--r--rts/sm/Storage.c3
3 files changed, 7 insertions, 2 deletions
diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h
index fadaa8c1a4..a5f4ed6f36 100644
--- a/includes/rts/storage/GC.h
+++ b/includes/rts/storage/GC.h
@@ -75,6 +75,7 @@ typedef struct generation_ {
bdescr * large_objects; // large objects (doubly linked)
memcount n_large_blocks; // no. of blocks used by large objs
+ memcount n_large_words; // no. of words used by large objs
memcount n_new_large_words; // words of new large objects
// (for allocation stats)
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 93606451cf..03c306857e 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -578,6 +578,7 @@ GarbageCollect (nat collect_gen,
freeChain(gen->large_objects);
gen->large_objects = gen->scavenged_large_objects;
gen->n_large_blocks = gen->n_scavenged_large_blocks;
+ gen->n_large_words = countOccupied(gen->large_objects);
gen->n_new_large_words = 0;
}
else // for generations > N
@@ -589,13 +590,15 @@ GarbageCollect (nat collect_gen,
for (bd = gen->scavenged_large_objects; bd; bd = next) {
next = bd->link;
dbl_link_onto(bd, &gen->large_objects);
- }
+ gen->n_large_words += bd->free - bd->start;
+ }
// add the new blocks we promoted during this GC
gen->n_large_blocks += gen->n_scavenged_large_blocks;
}
ASSERT(countBlocks(gen->large_objects) == gen->n_large_blocks);
+ ASSERT(countOccupied(gen->large_objects) == gen->n_large_words);
gen->scavenged_large_objects = NULL;
gen->n_scavenged_large_blocks = 0;
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 755c65427c..dd2ee31088 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -78,6 +78,7 @@ initGeneration (generation *gen, int g)
gen->n_old_blocks = 0;
gen->large_objects = NULL;
gen->n_large_blocks = 0;
+ gen->n_large_words = 0;
gen->n_new_large_words = 0;
gen->scavenged_large_objects = NULL;
gen->n_scavenged_large_blocks = 0;
@@ -951,7 +952,7 @@ W_ countOccupied (bdescr *bd)
W_ genLiveWords (generation *gen)
{
- return gen->n_words + countOccupied(gen->large_objects);
+ return gen->n_words + gen->n_large_words;
}
W_ genLiveBlocks (generation *gen)