[MLton] RE: card/cross map in heap

Matthew Fluet fluet at tti-c.org
Wed Jul 16 13:51:57 PDT 2008


On Fri, 27 Jun 2008, Nicolas Bertolotti wrote:
> The problem comes from the fact the remapHeap() function now succeeds too often.
>
> As a matter of fact, it now always succeeds when it is not able to grow 
> the heap and the current heap size is greater or equals minSize.

Right, on a platform with mremap (currently, only linux), a heap can 
always be successfully resized to its current size (or a smaller size).

> Then, when it is no longer possible to grow the size of the heap without 
> dumping it to the disk, the application continues to run without dumping 
> to disk until minSize really gets bigger than the current heap size.
>
> This really slows down the execution as, it is much better in that case 
> to dump the heap to disk and be able to allocate a bigger buffer than to 
> keep going and entering GC every time we need to allocate a few bytes.

But, only if doing the dump really gets you a larger heap.  If the program 
has live data close the the maximum contiguous map that mmap can allocate, 
then you will not only GC whenever allocating a few bytes, but you will 
also dump the heap to disk.  In that situtation, you are actually better 
off sticking with the existing heap, because paging to disk is so 
expensive.

> On the other hand, the fact that we guarantee that we try to allocate 
> minSize bytes is a good thing in the context of the createHeap() 
> function as it guarantees that the application won't crash until we 
> really run out of memory.

Right.  After we page the heap to disk, we've freed as much memory as we 
possibly can.  If at that point we can't create a heap of minSize, then we 
are really out of memory.

> In order to solve the issue, I have added the following piece of code at 
> the beginning of the remapHeap() function (see the attached patch, based 
> on the one you previously sent):
>  if (desiredSize > minSize && h->size == minSize)
>    minSize = align(minSize + backoff, s->sysvals.pageSize);
> I am not sure it is the best thing to do, but it works fine in my case.

This simply demands 'proper' growth from resizeHeap when the current heap 
is minSize.  As far as I can tell, this change will simply cause remapHeap 
to bail out before attempting to mremap to the original minSize (= current 
heap size).  Depending on rounding, it might attempt a mremap at a size 
that is a few pages smaller than desiredSize - 15*backoff, but it would be 
unusual for one the to succeed and the other fail.

With the above patch, what behavior do you see?  Does it go
   remapHeap fail; createHeap fail; write heap; createHeap succeed; read heap
or does it go
   remapHeap fail; createHeap succeed
And what are the sizes of the heaps that fail and succeed?


I'm not sure that there is a really principled way to make the decisions 
about keeping vs dumping the current heap.  What we really want is the 
ability to ask the question: if I unmap this memory, can I mmap this size? 
It seems that mremap should nearly approximate the answer to that question 
(since it is allowed to move the base address of the mapping), but your 
experience above seems to suggest that there are situations where we 
cannot mremap from the current heap size to even a slightly larger heap, 
but if we unmap (a portion of) the current heap (either by shrinking it or 
paging it to disk and releasing it), then we can mmap something larger.




More information about the MLton mailing list