Defstruct and Defclass as macros

The SBCL version

(macroexpand-1 '(defstruct spoint (x y)))

(PROGN
 (SB-KERNEL:WITH-SINGLE-PACKAGE-LOCKED-ERROR (:SYMBOL 'SPOINT
                                              "defining ~A as a structure"))
 (SB-KERNEL::%DEFSTRUCT '#
                        '#(#
                           #)
                        (SB-C:SOURCE-LOCATION))
 (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
   (SB-KERNEL::%COMPILER-DEFSTRUCT '#
                                   '#(#
                                      #)))
 (DECLAIM (FTYPE (SB-INT:SFUNCTION (&KEY (:X T)) SPOINT) MAKE-SPOINT))
 (DEFUN MAKE-SPOINT (&KEY ((:X #:DUM947) Y))
   (SB-KERNEL::%MAKE-STRUCTURE-INSTANCE-MACRO
    # '((:SLOT T . 1)) #:DUM947))
 (LOCALLY
  (DECLARE (NOTINLINE SB-KERNEL:FIND-CLASSOID))
  (SETF (SB-KERNEL::STRUCTURE-CLASSOID-CONSTRUCTOR
         (SB-KERNEL:FIND-CLASSOID 'SPOINT))
          #'MAKE-SPOINT))
 'SPOINT)

(macroexpand-1 '(defclass point () (x y)))

(PROGN
 (EVAL-WHEN (:COMPILE-TOPLEVEL)
   (SB-PCL::%COMPILER-DEFCLASS 'POINT 'NIL 'NIL '(Y X)))
 (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE)
   (LET ()
     (SB-PCL::LOAD-DEFCLASS 'POINT 'STANDARD-CLASS 'NIL
                            (LIST
                             (LIST* :NAME 'X :READERS 'NIL :WRITERS 'NIL
                                    :INITARGS 'NIL 'NIL)
                             (LIST* :NAME 'Y :READERS 'NIL :WRITERS 'NIL
                                    :INITARGS 'NIL 'NIL))
                            (LIST :DIRECT-DEFAULT-INITARGS NIL) 'NIL 'NIL
                            '(Y X) (SB-C:SOURCE-LOCATION) 'NIL))))

The Allegro CL version

(macroexpand-1 '(defstruct spoint (x y)))

(PROGN (PROGN (EVAL-WHEN (COMPILE)
                (EXCL::CHECK-LOCK-DEFINITIONS-COMPILE-TIME 'SPOINT :TYPE 'DEFSTRUCT (SYSTEM:CE-GET 'SPOINT 'EXCL::%STRUCTURE-DEFINITION)))
              (EVAL-WHEN (LOAD EVAL) (EXCL::CHECK-LOCK-DEF-DEFSTRUCT 'SPOINT)) (RECORD-SOURCE-FILE 'SPOINT :TYPE :TYPE))
       (PROGN (EVAL-WHEN (COMPILE) (PUSH 'SPOINT-X EXCL::.FUNCTIONS-DEFINED.)) (RECORD-SOURCE-FILE 'SPOINT-X)
              (SETF (SYMBOL-FUNCTION 'SPOINT-X) (EXCL::GET-BUILT-IN-ACCESSOR 1)))
       (DEFSETF SPOINT-X EXCL::DEFSTRUCT-SLOT-DEFSETF-HANDLER 1) (DEFUN MAKE-SPOINT (&KEY (#:X Y)) (SYSTEM::NEW-STRUCT 'SPOINT #:X))
       (DEFINE-COMPILER-MACRO MAKE-SPOINT (&WHOLE EXCL::WHOLE &REST REST)
         (LET ((EXCL::INITS #)) (IF EXCL::INITS (EXCL::BQ-LIST `LET* EXCL::INITS #) EXCL::WHOLE)))
       (EXCL::DEFINEF COPY-SPOINT (SYMBOL-FUNCTION 'COPY-STRUCTURE)) (EXCL::DEFINEF SPOINT-P (EXCL::GET-DD-PREDICATE-CLOSURE 'SPOINT))
       (EVAL-WHEN (LOAD EVAL)
         (LET ((EXCL::NEW #))
           (EXCL::COMPUTE-STRUCT-CPL EXCL::NEW)
           (EXCL::NOTIFY-CLOS-OF-NEW-STRUCTURE 'SPOINT EXCL::NEW)
           (EVAL-WHEN (LOAD EVAL) (SETF # EXCL::NEW))))
       (EVAL-WHEN (COMPILE)
         (LET ((EXCL::OLD #) (EXCL::NEW #))
           (SETF (EXCL::DD-INCLUDED-BY EXCL::NEW) (IF EXCL::OLD #))
           (EXCL::COMPUTE-STRUCT-CPL EXCL::NEW)
           (EXCL::NOTIFY-CLOS-OF-NEW-STRUCTURE 'SPOINT EXCL::NEW SYSTEM:*COMPILATION-UNIT-ENVIRONMENT*)
           (SYSTEM:CE-PUTPROP 'SPOINT EXCL::NEW 'EXCL::%STRUCTURE-DEFINITION)))
       ...)

(macroexpand-1 '(defclass point () (x y)))

(PROGN NIL (EVAL-WHEN (COMPILE) (EXCL::CHECK-LOCK-DEFINITIONS-COMPILE-TIME 'POINT :TYPE 'DEFCLASS (FIND-CLASS 'POINT NIL)))
       (RECORD-SOURCE-FILE 'POINT :TYPE :TYPE)
       (EXCL::ENSURE-CLASS-1 'POINT :DIRECT-SUPERCLASSES 'NIL :DIRECT-SLOTS (LIST (LIST ':NAME 'X) (LIST ':NAME 'Y))))

Defstruct vs Defclass: a 2x difference

I created a million instances of each (the structure spoint, and the class point), with randomized members, and the former took about 50 milliseconds, while the latter took about 100 milliseconds. Without obsessing over absolute numbers (this is a reasonable recent linux box), I believe the takeaway is that you should avoid used heavy CLOS until you really need to.

CL-USER> (defstruct spoint xp yp)
SPOINT
CL-USER> (time
(dotimes (i 1000000)
(make-spoint :xp (random 1000000) :yp (random 1000000))))
Evaluation took:
0.054 seconds of real time
0.050000 seconds of total run time (0.050000 user, 0.000000 system)
92.59% CPU
172,978,648 processor cycles
31,981,568 bytes consed

CL-USER> (defclass point () ((xp :initarg :xp) (yp :initarg :yp)))
#<STANDARD-CLASS POINT>
CL-USER> (time
(dotimes (i 1000000)
(make-instance 'point :xp (random 1000000) :yp (random 1000000))))
Evaluation took:
0.102 seconds of real time
0.100000 seconds of total run time (0.100000 user, 0.000000 system)
[ Run times consist of 0.020 seconds GC time, and 0.080 seconds non-GC time. ]
98.04% CPU
16 lambdas converted
324,534,044 processor cycles
64,606,960 bytes consed

Update: These figures are from SBCL, but I tried the same on AllegroCL and got identical results.

Of course the other takeaway is that everything is really really fast.