[MLton] callcc and space use

Matthew Fluet fluet at tti-c.org
Thu Feb 14 07:09:01 PST 2008


On Thu, 14 Feb 2008, Vesa Karvonen wrote:
> On Feb 14, 2008 5:11 AM, Matthew Fluet <fluet at tti-c.org> wrote:
>> I think I agree with Dan here.  MLton's default thread shrinking policy is
>> to attempt to halve the reserved size of the stack each time a stack is
>> live at a garbage collection.  [...]
>>
>> [...] In both versions, the "myrev" function calls "copy", which is a non-tail
>> recursive function.  Hence, "myrev" grows the stack proportional to the
>> size of the input list.  However, once the "copy" is done, the used stack
>> space is quite small.  In the callcc version, "fork" uses callcc and
>> copies only the used stack. [...] In the thread version, "fork" uses switch
>> and holds a reference to the current stack (with a large reserved size). [...]
>>
>> Perhaps a more aggressive stack resizing policy should be used when the
>> used/reserved ratio is very low.
>
> Interesting...  I think that something simple like allowing the
> reserved stack size to be at most the used stack size multiplied by a
> suitable factor (e.g. 4), which is larger than the factor (e.g. 2)
> used to grow/shrink the stack, should do the trick.  This should
> maintain the amortized linear time complexity of pushing/popping the
> stack and ensure that the (total) unused stack space is at most a
> constant factor of the used stack space (after a complete GC).

There was a (short) discussion of stack resizing policy a few years ago:
   http://mlton.org/pipermail/mlton/2004-April/025297.html

I suspect that it will be difficult to have a one-size-fits-all policy. 
When shrinking is too aggressive, you pay to grow the stack when a stack 
is resumed.  When shrinking isn't aggressive enough, you pay in space and 
GC time for the wasted space.  If you have a small number of preemptively 
scheduled threads, then no thread is idle for too long, and it makes more 
sense to not resize stacks too aggressively.  If you have a large number 
of idle threads, then it makes sense to resize the stacks more 
aggressively.

On the other hand, your policy of requiring a paused stack to have have 
reserved <= 4 * used seems reasonable.  But, with that policy, does it 
matter whether there is the additional policy that we halve the reserved 
size each time a paused thread lives through a GC?

BTW, I also noticed that the stack resizing policy is only in effect for a 
copying GC (minor or major).  The mark-compact GC will not resize paused 
stacks, though I don't see why I couldn't.




More information about the MLton mailing list