Commit a68df77e authored by Simon Marlow's avatar Simon Marlow
Browse files

Reduce fragmentation when using +RTS -H (with or without a size)

parent 0a7c5b89
...@@ -389,6 +389,41 @@ finish: ...@@ -389,6 +389,41 @@ finish:
return bd; return bd;
} }
//
// Allocate a chunk of blocks that is at most a megablock in size.
// This API is used by the nursery allocator that wants contiguous
// memory preferably, but doesn't require it. When memory is
// fragmented we might have lots of large chunks that are less than a
// full megablock, so allowing the nursery allocator to use these
// reduces fragmentation considerably. e.g. on a GHC build with +RTS
// -H, I saw fragmentation go from 17MB down to 3MB on a single compile.
//
bdescr *
allocLargeChunk (void)
{
bdescr *bd;
nat ln;
ln = 5; // start in the 32-63 block bucket
while (ln < MAX_FREE_LIST && free_list[ln] == NULL) {
ln++;
}
if (ln == MAX_FREE_LIST) {
return allocGroup(BLOCKS_PER_MBLOCK);
}
bd = free_list[ln];
n_alloc_blocks += bd->blocks;
if (n_alloc_blocks > hw_alloc_blocks) hw_alloc_blocks = n_alloc_blocks;
dbl_link_remove(bd, &free_list[ln]);
initGroup(bd);
IF_DEBUG(sanity, memset(bd->start, 0xaa, bd->blocks * BLOCK_SIZE));
IF_DEBUG(sanity, checkFreeListSanity());
return bd;
}
bdescr * bdescr *
allocGroup_lock(nat n) allocGroup_lock(nat n)
{ {
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "BeginPrivate.h" #include "BeginPrivate.h"
bdescr *allocLargeChunk (void);
/* Debugging -------------------------------------------------------------- */ /* Debugging -------------------------------------------------------------- */
extern nat countBlocks (bdescr *bd); extern nat countBlocks (bdescr *bd);
......
...@@ -437,10 +437,16 @@ allocNursery (bdescr *tail, nat blocks) ...@@ -437,10 +437,16 @@ allocNursery (bdescr *tail, nat blocks)
// tiny optimisation (~0.5%), but it's free. // tiny optimisation (~0.5%), but it's free.
while (blocks > 0) { while (blocks > 0) {
n = stg_min(blocks, BLOCKS_PER_MBLOCK); if (blocks >= BLOCKS_PER_MBLOCK) {
bd = allocLargeChunk(); // see comment with allocLargeChunk()
n = bd->blocks;
} else {
bd = allocGroup(blocks);
n = blocks;
}
blocks -= n; blocks -= n;
bd = allocGroup(n);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
initBdescr(&bd[i], g0, g0); initBdescr(&bd[i], g0, g0);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment