From: Pascal C. <pc...@p-...> - 2009-09-07 06:38:56
|
On 7 Sep 2009, at 08:16, John Fremlin wrote: > Hi Pascal, > > Pascal Costanza <pc...@p-...> writes: > >> On 4 Sep 2009, at 13:59, John Fremlin wrote: >> >>> We (MSI) have just released a development version of our memory >>> mapped >>> 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. >>> >>> http://github.com/ilitirit/manardb/tree/master >>> >>> Object instantiation seems a little slow on SBCL (just my impression >>> compared to Allegro 8.1 -- could be completely wrong) and I wonder >>> if >>> 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 >> code: >> >> + 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 >> instead. > > Thanks for this input. I wasn't aware of that (it isn't covered in > AMOP > 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 shared-initialize." > I cargo culted the idea from Elephant. But you are > quite correct according to > http://clisp.cons.org/impnotes/mop-classes.html#mop-cl-init-mo > > 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 functions. ;) >>> 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 > initargs) > (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))) > (t > (let ((class (class-of instance))) > (setf (%ptr instance) (mm-metaclass-alloc class)) > > ;;; XXX this is a horrible hack because we don't support unbound > slots > ;;; 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)))))))))) > instance) 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 slot-xyz-using-class methods. >> 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 > this > 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 -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel Software Languages Lab Pleinlaan 2, B-1050 Brussel, Belgium |