[plt-dev] Re: Fine-tuning performance

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Fri Jan 29 14:22:06 EST 2010

(Thanks for the alert about my mail!)

> On Fri, Jan 29, 2010 at 12:27 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:
> > One, there are some functions that I memoize with a weak hash table.
> > Are there any sorts of values that will never be collected, and will
> > persist forever in the hash table?  For instance, do word-sized values
> > like fixnums or ASCII characters stick around?

Fixnums are the only true special case.

Some other values are difficult to reason about:

 * Latin-1 characters are always reachable, because they are `eq?' when
   they're `equal?', and there's a table that refers to all of them.

 * Constants like `#t', `#f', `(void)', `eof', etc. are always
   reachable from somewhere.

 * Interned symbols are GCed, but you can't generally predict whether
   anyone else is using a given symbol.

 * Some common flonums like `+inf.0' are semi-interned; a primitive
   that produces `inf.0' might always produce the same one in the sense
   of `eq?'. More generally, non-fixnum numbers are a lot like symbols,
   it in that someone else might hold onto one for some reason.

 * A quoted value stays reachable as long as the code is reachable for
   the expression that produced it.

Of course, weak references usually work best on the results of
functions that offer a guarantee of allocation, such as `list'
(documented) or `cons' (not documented; oops).

When I put my compiler hat on, I'm not always happy with allocation
guarantees, but weak references are why they're (supposed to be)

> > Two, I've gotten the impression that special casing variable-arity
> > functions at some fixed arities via case-lambda will speed up the
> > common case.  Is this true, 

Yes, typically.

> and if so how significant is the
> > difference (as a general order of magnitude)? 

The potential improvement is mostly in avoiding a list allocation for
the rest argument and then pulling values out of that list.

> > Is there some cutoff
> > past which this specialization no longer pays off?  I know there's no
> > a priori precise answer, I'd have to experiment for that, but if
> > there's a representation change (e.g. functions calls with more than 8
> > arguments get allocated as lists regardless) it would be useful to
> > know.

There's no such cut-off. A list is never created for function arguments
unless you use a rest arg. So, the trade-off is list creation versus
the number of cases to check and the extra code for each case.

As a minor complication, a list is not created for a rest argument if
the argument identifier isn't used in the procedure body (after the
optimizer's simplifications).

Another complication is that the compiler doesn't currently inline
applications of `case-lambda's. It should, and maybe it will soon. As
of a few days ago, the compiler also didn't inline applications of a
procedure with rest args, but now it does (because I found a use that
needed it).

Posted on the dev mailing list.