Re: threads and GC in LWW 4.2
* davef wrote:
> Most of the allocation in Tim's test is for the stacks of the
> processes. Stacks are allocated in generation 2 by default, which
> accounts for the effects observed. To improve the performance, try
> setting SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH*.
Thanks for explaining this. I'd worked out, I think, that there must
have been some allocation in the generation 2, and stacks is the
obvious thing (especially as they're relatively large).
> LispWorks keeps a cache of stacks, so 'normal' creation and
> destruction of processes normally does not cause a problem. The stack
> of a dead process is put in the cache and then re-used. The number of
> stacks in the cache is limited to the value of
> SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH*, which defaults to 10. The
> test creates more than 10 processes and then they all die, so only
> 10 of the stacks are cached and the rest are not collected until the
> user calls (MARK-AND-SWEEP 2). This is what causes the enlargement of
> memory.
Yes. One thing I tried was to set collect-second-generation (? the
function name, but the one that says to GC the second generation), and
this didn't seem to help. I'm slightly mystified by that, but
everything else makes sense. (Actually, maybe this is because there
was not enough allocation in 0 and 1 to force a GC of 2?)
> If the application needs this fast turnover of processes, then try
> setting SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH* to a larger value. For
> example, after doing
> (SETQ SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH* 110)
> for me
> (TS-NATIVE 100 100)
> runs in a few minutes and doesn't grow after the initial growth.
> Since a stack is approximately 65Kb, setting this to 110 will make a
> cache of around 7Mb.
If I understand correctly, the bad situation is if more than
SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH* have died with no new process
creation in the meantime, then if the death rate exceeds the birth
rate stacks will `leak' until a GC of 2. Is that right?
> Maybe we should make the initial value of
> SYS::*DEFAULT-STACK-GROUP-LIST-LENGTH* larger, but it is not obvious
> since this issue has not arisen before AFAICT. A larger value should
> be harmless since in normal circumstances the cache is not going to
> grow much anyway. Anyway, we have have decided to export and document
> this variable, but not change the initial value at this stage.
> We would be interested to hear of a 'real-life' (non test-suite!)
> situation where such a large turnover of processes is useful.
I doubt my system will have this problem. I'm intending to create a
pool of processes and then feed them with mailboxes, so my stacks will
be very long-lived.
> There is a general mechanism in LispWorks for freezing the promotion
> mechanism similarly to what Francis described for ACL. See
> LW:BLOCK-PROMOTION. I tried this in the test case, and found that it
> does not improve performance, because stacks are allocated in
> generation 2 regardless. We'll improve the doc to mention this
> subtlety.
The other thing is that I *think* LW:BLOCK-PROMOTION won't work in
multithreaded contexts. When I macro-expanded it it seemed to work by
binding an internal special variable, which binding will, I guess not
be visible outside the process that created it. Unless there is some
deep magic I don't see how the GC can tell if BLOCK-PROMOTION is in
effect in another thread. I think it should assign the variable in an
unwind-protect or something. But maybe I misunderstand this...
Anyway, thanks for explaining what is happening. I'm now reassured
that bad things won't happen in real life.
--tim