[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