CMUCL (was Re: Benevolent Dictatorship)

Fred Gilham gilham@csl.sri.com
Sat, 21 Mar 1998 11:05:10 -0800


My experience with CMUCL has been very positive.  I've done a lot of
benchmarking, comparing it to ACL 4.3 running under Linux, and CMUCL
is as fast, or sometimes faster, in almost every area.  CMUCL has
improved a lot over the last few years.

The one place where CMUCL falls down is in instance-creation under
CLOS.  Note that most CLOS operations besides this one are as fast or
faster in CMUCL as in ACL.

The reason CLOS instance-creation is slow under CMUCL is that it uses
the generic PCL code.  There's some discussion of how to fix this kind
of thing in a brief paper by D. Scott Cyphers and David A. Moon that I
ran across called ``Optimizations in the Symbolics CLOS
Implementation''.  I've appended their comments about make-instance to
the end of this message.  The enhancements they describe are compiler
dependent but there's already support for them in the PCL code.
Anyone interested in this should take a look at the file
`construct.lisp' in the PCL code.  It describes the idea and gives the
hooks that would allow implementing the optimizations necessary to
speed up make-instance.  I guess one would have to understand both
CMUCL's compiler and CLOS to do it.

This is from the paper I mentioned:

MAKE-INSTANCE

The example implementation of MAKE-INSTANCE given in the CLOS
specification is highly interpretive, and therefore slow.  The following
operations can be eliminated or optimized:  mapping a class name to a
class object, receiving keyword arguments, checking for invalid keyword
arguments, defaulting unsupplied initialization arguments, evaluating
slot initforms, and initializing slots from initialization arguments and
slot initforms.  The necessary operations of allocating storage and
calling user-supplied initialization methods can be streamlined.

Mapping a constant class name to a constant class object is ordinary
constant-folding.

A call to MAKE-INSTANCE with a constant class and constant keywords is
optimized into a call to an automatically generated constructor function
that specializes in creating objects of that class with those
initialization arguments.  This eliminates class lookup and all keyword
argument processing (positional arguments are used), and simplifies
defaulting of initialization arguments since the supplied/unsupplied
status of each initialization argument is fixed.

Other calls to MAKE-INSTANCE still call the MAKE-INSTANCE generic
function, but dispatch to an automatically generated constructor method
that specializes in creating objects of that class.  Keyword argument
processing and defaulting are still necessary in this case.

The constructor function or method uses inlining of initforms, inlining
of system-defined method bodies, direct calls to user-defined method
functions, loop unrolling, elimination of redundant slot-boundp tests,
and minimized instruction sequences for storing into slots.  Since the
system-defined methods called by MAKE-INSTANCE are highly interpretive
(they get the list of slot-descriptions, iterate over them, check if the
slot has any initargs, etc.) the inlining is not done by analyzing the
body of the real method, but instead by a specialized generator function
for each method.  The generator functions are similar to macros, but
have access to the class definition and to the sets of initialization
arguments that are known to be supplied, defaulted, or might be either
supplied or defaulted.

These optimizations eliminate all run-time references to the class and
slot-definition metaobjects.  The information contained in those objects
has been converted into compiled code instructions.  With these
optimizations, MAKE-INSTANCE on Ivory is slightly faster than MAKE-ARRAY
and almost as fast as MAKE-LIST, measured for two slots or elements.

Some care is required to regenerate the automatically generated constructor
functions and methods if the class is redefined, and to arrange to generate
them at load-time rather than at run-time so that the first instantiation of
each class is not slowed down by calling the constructor generator and the
compiler.