[GHC] #7831: Bad fragmentation when allocating many large objects

GHC cvs-ghc at haskell.org
Sat Apr 13 11:17:23 CEST 2013


#7831: Bad fragmentation when allocating many large objects
-----------------------------+----------------------------------------------
Reporter:  ezyang            |          Owner:  ezyang          
    Type:  bug               |         Status:  new             
Priority:  normal            |      Component:  Runtime System  
 Version:  7.7               |       Keywords:                  
      Os:  Unknown/Multiple  |   Architecture:  Unknown/Multiple
 Failure:  None/Unknown      |      Blockedby:                  
Blocking:                    |        Related:                  
-----------------------------+----------------------------------------------
 Consider our good old friend, the space-leaky list program:

 {{{
 import Control.Exception
 import System.Environment

 f n = let xs = [1..n] in sum xs * product xs

 main = do
     [n] <- getArgs
     evaluate (f (read n :: Integer))
 }}}

 It is not surprising that this program is quite the memory guzzler; what
 is surprising is how much GHC *wastes* when evaluating this program:

 {{{
 Fragmentation, wanted 95 blocks,  105 MB free
 }}}

 (For reference, a block is 4k, so 95 blocks is a measly 380k!)  The
 magnitude of the problem can be seen in this graphic:

 [[Image(http://web.mit.edu/~ezyang/Public/fragmentation-ghc.png)]]

 (The x-axis takes advantage of the fact that the number of requested
 blocks increases ~linearly over time, since we keep multiplying the
 integer which adds a constant number of extra bytes to the representation;
 unused free memory corresponds to blocks of free memory in GHC's free
 list, which it is holding onto from the OS but not using to store user
 data.)

 When the requested allocations are *just* large enough (just slightly over
 half a megablock, or 128 blocks), we start allocating a megablock per
 allocation and waste half of the megablock, since none of the leftovers
 are ever large enough to store any of the later allocations.

 Can we do anything about this? One possibility is to occasionally check
 how much space we're losing to fragmentation, and everyone once in a while
 pay the cost of copying tenured large objects and pack them together in a
 megablock group (obviously one wants to avoid doing this too often, since
 copying large objects is expensive!) I'm open to better suggestions
 though! (Apologies if this is a duplicate; I didn't see any open tickets
 with the word "fragmentation" in them).

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7831>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler



More information about the ghc-tickets mailing list