GC performance - was Re: [gclist] GC topics

Darius Blasband darius@phidani.be
Sat, 24 Feb 1996 19:40:03 +0100 (MET)


> 
> I didn't try much to decipher the C code generated from YAFL, but 
> here's a concern:  if you're storing all pointer variables on a separate
> stack in main memory, they're not going to be register-allocated unless
> you're doing something clever I don't know about.  In general, reads
> and writes of pointer variables will go through memory.
Well, not entirely. We keep a stack of pointers to pointers, first
level variables remain on the system stack. However, you are absolutely
right when you state that they cannot be register allocated, unless
the system can statically decide that the method is safe (that is, it
cannot induce any new allocation) in which case it compiles to a pretty
naive C function (not more readable). In practice, the proportion of
such methods is very important (60 to 70%), which makes this kind
of optimization very efficient.

(And by the way, I just thought we might improve the performance of this
stuff by storing read/only variables (THIS, formals) on the
value stack, in which case we don't need to take care of their address
anymore, and they can then be register allocated if the supporting
C compiler can do it;

> 
> For RScheme, we do two things to avoid this.
> 
> Our abstract machine uses a register model, not a stack model, and we can
> put some of our abstract registers in hardware registers with some compilers
> (e.g., the GNU C compiler).  So with a little per-platform fiddling of a
> header file, we can get some real registers to use for the most important
> ones.  (But SPARCs and Intel x86's are a pain because of an awkward shortage
> of plain old global registers.)  Of course, this is not portable.  We
> can generate portable C, but it's a bit slower.
Funny. We came to exactly the same conclusion not so long ago: we considered
using gcc's global registers for usage-intensive global variables,
and it did not work out very well on x86's...

> 
> The other trick---which is portable---is to compile Scheme expressions
> into C expressions, so that the intermediate values (temporaries) of
> those expressions can be register-allocated by the C compiler in the
> usual way.  For this, we rely on the fact that we only GC at safe
> points, and C expressions never cross safe points.  (That takes a little
> work in the compiler, but not much---we just don't glom things together
> into C expressions if they include a safe point.)
Since YAFL expressions compile to reasonably naive C expressions, I guess
we have something similar, except for the fact that we keep what we call
a value stack for short lived allocations, when evaluating parts of
an expression, for instance...

> 
> All of this should let us generate decent code while supporting full
> fine-grained continuation capture, copying GC, fine-grained pointer
> swizzling, etc.  Right now, other aspects of the compiler need to be
> improved before we can really tell how well this strategy works---we're
> generating mediocre code, but mostly for other reasons.  Ultimately, I
> think it will cost us significantly, but not prohibitively, relative
> to generating C in the usual way and relying on conservative GC.  (For
> some criterion of "significantly" and "prohibitively", to be reverse
> engineered to fit the eventual results. :-)
> 
> 
As I wrote a couple of times already, it did cost us 20% I leave it to
your appreciation whether it is significant or prohibitive...

Regards

D.