SBCL hacks

modules

Small useful things for SBCL. Git repo, tarball.

Measuring list sequentialness

sequentialness is a function which tells you how sequential an object is, which really means how sequential the backbone of a list is. See the LW version for documentation.

Example:

> (sequentialness (make-list 5) :debug t)
       0:       70058040C7       70058040B7              -10 (-16)
       1:       70058040B7       70058040A7              -10 (-16)
       2:       70058040A7       7005804097              -10 (-16)
       3:       7005804097       7005804087              -10 (-16)
1
4
t

You can see that make-list builds lists backwards in the way you probably would write it.

You will need iterate to use this.

This is closely similar to the LW version, on which it is based.

Standard-instance slots

The AMOP MOP provides a mechanism to make slot access faster – less slow would be a better term – in limited cases. with-sia-slots is a macro which is like with-slots but uses standard-instance-access. It will work in the cases that standard-instance-access does: it doesn’t check that those requirements are met. It needs to find the locations for the slots being accessed, which involves some overhead: it’s probably most useful for cases where one or more slots is going to be accessed a large number of times.

This macro really only depends on the AMOP MOP: it should work unchanged in other implementations. The module may at some point be renamed to reflect that.

The speedup is significant: given

(needs
 ((:org.tfeb.sbcl.sia-slots
   :org.tfeb.tools.timing)
  :compile t :use t))

(defclass a ()
  ((i :initform 0)))

(defmethod inc-i/sv ((a a) n)
  (declare (type fixnum n)
           (optimize speed))
  (with-slots (i) a
    (dotimes (_ n)
      (incf (the fixnum i)))
    a))

(defmethod inc-i/sia ((a a) n)
  (declare (type fixnum n)
           (optimize speed))
  (with-sia-slots (i) a
    (dotimes (_ n)
      (incf (the fixnum i)))
    a))

(defun time-sv (&key (n 10000000))
  (let ((a (make-instance 'a)))
    (timing (:tries 10 :divider (* n 2))
      (inc-i/sv a n))))

(defun time-sia (&key (n 10000000))
  (let ((a (make-instance 'a)))
    (timing (:tries 10 :divider (* n 2))
      (inc-i/sia a n))))

(defun estimate-sia-speedup (&key (n 100000000))
  (/ (time-sv :n n)
     (time-sia :n n)))

then

> (estimate-sia-speedup)
11.171078