Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch : ghc-7.6
http://hackage.haskell.org/trac/ghc/changeset/a737b1efdb433f87689f391b8402d2bd8799a8d7 >--------------------------------------------------------------- commit a737b1efdb433f87689f391b8402d2bd8799a8d7 Author: Simon Marlow <marlo...@gmail.com> Date: Fri Sep 21 13:11:22 2012 +0100 Allow allocNursery() to allocate single blocks (#7257) Forcing large allocations here can creates serious fragmentation in some cases, and since the large allocations are only a small optimisation we should allow the nursery to hoover up small blocks before allocating large chunks. MERGED from commit 1f5d83648dfda39d999eb8a9e8192339b3eea540 >--------------------------------------------------------------- rts/sm/BlockAlloc.c | 8 +++++++- rts/sm/Storage.c | 16 ++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/rts/sm/BlockAlloc.c b/rts/sm/BlockAlloc.c index 93e06da..cd4aca1 100644 --- a/rts/sm/BlockAlloc.c +++ b/rts/sm/BlockAlloc.c @@ -393,12 +393,18 @@ finish: // Allocate a chunk of blocks that is at least min and at most max // blocks 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 +// memory is fragmented we might have lots of 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. // +// Further to this: in #7257 there is a program that creates serious +// fragmentation such that the heap is full of tiny <4 block chains. +// The nursery allocator therefore has to use single blocks to avoid +// fragmentation, but we make sure that we allocate large blocks +// preferably if there are any. +// bdescr * allocLargeChunk (nat min, nat max) { diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index e504c28..1b7577a 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -438,16 +438,12 @@ allocNursery (bdescr *tail, W_ blocks) // tiny optimisation (~0.5%), but it's free. while (blocks > 0) { - if (blocks >= BLOCKS_PER_MBLOCK / 4) { - n = stg_min(BLOCKS_PER_MBLOCK, blocks); - bd = allocLargeChunk(16, n); // see comment with allocLargeChunk() - // NB. we want a nice power of 2 for the minimum here - n = bd->blocks; - } else { - bd = allocGroup(blocks); - n = blocks; - } - + n = stg_min(BLOCKS_PER_MBLOCK, blocks); + // allocLargeChunk will prefer large chunks, but will pick up + // small chunks if there are any available. We must allow + // single blocks here to avoid fragmentation (#7257) + bd = allocLargeChunk(1, n); + n = bd->blocks; blocks -= n; for (i = 0; i < n; i++) { _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc