[GHC] #8609: Clean up block allocator
GHC
ghc-devs at haskell.org
Wed Dec 11 01:11:19 UTC 2013
#8609: Clean up block allocator
-------------------------------------+-------------------------------------
Reporter: ezyang | Owner: ezyang
Type: bug | Status: new
Priority: low | Milestone:
Component: Runtime System | Version: 7.7
Keywords: patch | Operating System: Unknown/Multiple
Architecture: Unknown/Multiple | Type of failure: Runtime
Difficulty: Easy (less than 1 | performance bug
hour) | Test Case:
Blocked By: | Blocking:
Related Tickets: |
-------------------------------------+-------------------------------------
For fun, I was reimplementing GHC's block allocator in Rust, and I noticed
that there are a number of things the current block allocator code does
that result in extra, unnecessary work:
* Upon a perfect match, `alloc_mega_group` initializes the returned block
group (`initGroup`). This is unnecessary, because the caller of
`alloc_mega_group` is responsible for initializing the block groups.
* The `initGroup` function uses the `blocks` to figure out how many block
descriptors it needs to initialize. However, in the case of a multi-
megablock group, blocks will larger than BLOCKS_PER_MBLOCK, so this
process will march into the first block and write information to block
descriptors which will be later be overwritten by the user data. So,
`initGroup` should cap at the block descriptors of the first megablock.
One can go even further: if a block group spans multiple megablocks, then
in practice, the only block descriptor we care about is the very first
one, since we're not allowed to have internal GC'd pointers to the block
group (as not every address in the group has a valid bdescr associated
with it).
* The commentary should add a bit about mblock groups. Essentially, the
mblock free list has a different set of invariants: the first mblock's
start pointers are guaranteed to be initialized (the mblock was
`initMBlock` 'd), and the blocks and link fields of the first bdescr will
be something appropriate; there are no other guarantees.
Here are the proposed functional changes (obviously some extra
documentation is necessary; replace the XXX marked expression with
BLOCKS_PER_MBLOCK if you want to do the more conservative changes for
larger than mblock block chains):
{{{
diff --git a/rts/sm/BlockAlloc.c b/rts/sm/BlockAlloc.c
index 18c167f..33530d8 100644
--- a/rts/sm/BlockAlloc.c
+++ b/rts/sm/BlockAlloc.c
@@ -170,7 +170,7 @@ initGroup(bdescr *head)
bdescr *bd;
W_ i, n;
- n = head->blocks;
+ n = head->blocks > BLOCKS_PER_MBLOCK ? 1 /* XXX */ : head->blocks;
head->free = head->start;
head->link = NULL;
for (i=1, bd = head+1; i < n; i++, bd++) {
@@ -278,7 +278,6 @@ alloc_mega_group (StgWord mblocks)
} else {
free_mblock_list = bd->link;
}
- initGroup(bd);
return bd;
}
else if (bd->blocks > n)
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8609>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list