Performance Optimization

time, sb-sprof (statistical profiler), sb-ext:*evaluator-mode* Declare types in hot code fixnum, double-float, simple-array element types Use specialized arrays

(simple-array double-float (*)), (unsigned-byte 8) Avoid consing in loops

Reuse buffers, avoid generic sequence functions in tight loops, use dynamic-extent for stack allocation

Prefer vectors over lists for random access aref is O(1), nth is O(n) Structures over CLOS for hot data Faster slot access inline small functions (declaim (inline f)) Check disassemble and compiler notes Look for generic-+ calls and boxing Hash table tests eq/eql are faster than equal

Use with-output-to-string or adjustable strings, not repeated concatenate lparallel for CPU-bound work GC tuning (SBCL)

(setf (sb-ext:bytes-consed-between-gcs) (* 200 1024 1024)), --dynamic-space-size

;; Before: generic arithmetic, boxed floats
(defun dot (a b)
  (loop for x across a for y across b sum (* x y)))

;; After: specialized arrays and declarations
(defun dot-fast (a b)
  (declare (type (simple-array double-float (*)) a b)
           (optimize (speed 3) (safety 0) (debug 0)))
  (let ((sum 0d0))
    (declare (type double-float sum))
    (dotimes (i (length a) sum)
      (incf sum (* (aref a i) (aref b i))))))

(let ((a (make-array 1000000 :element-type 'double-float :initial-element 1d0)))
  (time (dot-fast a a)))      ; TIME reports run time, GC time, and bytes consed
(defun sum-list (list)
  (let ((buffer (make-array 3)))
    (declare (dynamic-extent buffer))     ; may be stack-allocated
    (setf (aref buffer 0) (reduce #'+ list))
    (aref buffer 0)))