On 7 Sep 2009, at 08:16, John Fremlin wrote:
> Hi Pascal,
> Pascal Costanza <pc@...> writes:
>> On 4 Sep 2009, at 13:59, John Fremlin wrote:
>>> We (MSI) have just released a development version of our memory
>>> MOP database. There's a lot that can be improved with it but it
>>> has a
>>> test suite and has been bashing stuff out for a while.
>>> Object instantiation seems a little slow on SBCL (just my impression
>>> compared to Allegro 8.1 -- could be completely wrong) and I wonder
>>> there is something I'm doing wrong?
>> Not sure, there could be many reasons.
>> However, I can notice a few issues from taking a first look at the
>> + You define a method on shared-initialize for your
>> metaclass. According to the CLOS MOP specification, you are not
>> allowed to do that, your program is thus not portable. You have to
>> define methods on initialize-instance and reinitialize-instance
> Thanks for this input. I wasn't aware of that (it isn't covered in
> as far as I can see).
It is, in the section "Initialization of Class Metaobjects", where it
explicitly states that "portable programs must not define methods on
> I cargo culted the idea from Elephant. But you are
> quite correct according to
> It is now fixed and I've pushed the updates.
Make sure that these are :before/:after/:around methods, because the
spec also states that you must not define primary methods on those
>>> Unfortunately as all mmap slots are always boundp, we have to munge
>>> the general initialize-instance to set default slot values. This is
>>> quite unfortunate. Is there a more sensible way of doing this (along
>>> the lines of the way structure slots are handled)?
>> What do you mean by 'munge' (sorry, I'm not a native speaker)?
> I mean that the way I do it is not at all nice and pretty. I think
> it is
> probably clearer to show the code
> (defmethod initialize-instance :before ((instance mm-object) &rest
> (declare (optimize speed) (dynamic-extent initargs))
> (cond ((eq '%ptr (first initargs)) ;;; XXX this is for speed; if
> %ptr is given it must be first
> (setf (%ptr instance)
> (second initargs)))
> (let ((class (class-of instance)))
> (setf (%ptr instance) (mm-metaclass-alloc class))
> ;;; XXX this is a horrible hack because we don't support unbound
> ;;; not in shared-initialize because that is more likely to
> destroy the system's optimizations????
> (let ((slot-definitions (class-slots class)))
> (loop for s in slot-definitions do
> (when (and (slot-definition-memory-mapped s)
> (slot-definition-initfunction s))
> (unless (get-properties initargs (slot-definition-initargs s))
> (setf (slot-value-using-class class instance s)
> (funcall (slot-definition-initfunction s))))))))))
I guess this is where the overhead comes from. I don't see an obvious
way how to avoid the overhead. (Sorry.)
You could try to support unbound slots nonetheless, but this would
still lead to slower initializations because it would bypass certain
optimizations a CLOS implementations is allowed to do without your own
>> Note that you can also define methods on make-instance and allocate-
>> instance, if that helps.
> The situation when most instance creation occurs is when an object is
> instantiated from the database into a Lisp object (generally with one
> slot, (hopefully) a fixnum "mptr").
> It is possible for the object to have normal instance slots (caches or
> temporary slots). Those should be initialized according to the normal
> rules. It would be possible to generate an compiled function to do
> explicitly for all such slots -- firstly calling allocate-instance(?)
> directly and then the init-functions for each slot.
> One approach I was considering was to inherit from structure-class
> instead of standard-class, etc. This would finesse the
> initialisation as
> structure slots are also never unbound. But I think that is not really
> portable? (And perhaps not sensible)
Maybe you could initialize the memory in some other way (by writing
0's, for example), and then not use CLOS initialization at all for
such slots. Instead, invoke another generic function 'initialize-
memory-mapped-slots that can be specialized by a user as an :after
method on initialize-instance. Then you could at least bypass the
iteration through the slot definition metaobjects. Just an idea...
Pascal Costanza, mailto:pc@..., http://p-cos.net
Vrije Universiteit Brussel
Software Languages Lab
Pleinlaan 2, B-1050 Brussel, Belgium