@c Generated by the sb-manual contrib. Do not edit.

@node efficiency
@cindex efficicency
@chapter Efficiency

@menu
* Slot Access: slot access.
* Stack Allocation: stack allocation.
* Modular Arithmetic: modular arithmetic.
* Recognized Idioms: recognized idioms.
* Global and Always-bound Variables: global and always bound variables.
* Miscellaneous Efficiency Issues: miscellaneous efficiency issues.
@end menu

@node slot access
@cindex slot access
@section Slot Access

@menu
* Structure Object Slot Access: structure object slot access.
* Standard Object Slot Access: standard object slot access.
@end menu

@node structure object slot access
@subsection Structure Object Slot Access

Structure slot accessors are efficient only if the compiler is
able to open code them: compiling a call to a structure slot
accessor before the structure is defined, declaring one @code{notinline},
or passing it as a functional argument to another function causes
severe performance degradation.

@node standard object slot access
@subsection Standard Object Slot Access

The most efficient way to access a slot of a @code{standard-object} is
by using @code{slot-value} with a constant slot name argument inside a
@code{defmethod} body, where the variable holding the instance is a
specializer parameter of the method and is never assigned to. The
cost is roughly 1.6 times that of an open coded structure slot
accessor.

Second most efficient way is to use a CLOS slot accessor, or
@code{slot-value} with a constant slot name argument, but in circumstances
other than specified above. This may be up to 3 times as slow as the
method described above.

Example:

@example
(defclass foo () ((bar)))

;; Fast: specializer and never assigned to
(defmethod quux ((foo foo) new)
  (let ((old (slot-value foo 'bar)))
    (setf (slot-value foo 'bar) new)
    old))

;; Slow: not a specializer
(defmethod quux ((foo foo) new)
  (let* ((temp foo)
         (old (slot-value temp 'bar)))
    (setf (slot-value temp 'bar) new)
    old))

;; Slow: assignment to FOO
(defmethod quux ((foo foo) new)
  (let ((old (slot-value foo 'bar)))
    (setf (slot-value foo 'bar) new)
    (setf foo new)
    old))
@end example

Note that when profiling code such as this, the first few calls to the
generic function are not representative, as the dispatch mechanism is
lazily set up during those calls.

@node stack allocation
@section Stack Allocation

SBCL has fairly extensive support for performing allocations on the
stack when a variable or function is declared @code{dynamic-extent}. The
@code{dynamic-extent} declarations are not verified but are simply trusted
as long as @code{sb-ext:*stack-allocate-dynamic-extent*} is true.

@anchor{Variable sb-ext *stack-allocate-dynamic-extent*}
@vvindex @sortas{stack-allocate-dynamic-extent* sb-ext} *stack-allocate-dynamic-extent* [sb-ext]
@deffn{Variable} sb-ext:*stack-allocate-dynamic-extent*
If true (the default), the compiler believes @code{dynamic-extent} declarations
and stack allocates otherwise inaccessible parts of the object whenever
possible.
@end deffn
SBCL recognizes any value which a variable declared @code{dynamic-extent}
can take on as having dynamic extent. This means that, in addition
to the value a variable is bound to initially, a value assigned to a
variable by @code{setq} is also recognized as having dynamic extent when
the variable is declared @code{dynamic-extent}. Users can thus build
complex structures on the stack using iteration and @code{setq}.

At present, SBCL implements stack allocation for the following kinds
of values when they are recognized as having dynamic extent:

@itemize
@item @code{&rest} lists;

@item the results of @code{cons}, @code{list}, @code{list*}, and @code{vector};

@item the result of simple forms of @code{make-array}: stack allocation is
  possible only if the resulting array is known to be both simple
  and one-dimensional, and has a constant @code{:element-type};

@quotation
@cindex safety, optimization quality
@cindex optimization quality safety
@strong{Warning}: Stack space is limited, so allocation of a large
vector may cause stack overflow. Stack overflow checks are
done except in 0 safety policies.
@end quotation

@item closures defined with @code{flet} or @code{labels} with a bound @code{dynamic-extent}
  declaration;

@item anonymous closures defined with @code{lambda};

@item user-defined structures when the structure constructor defined using
  @code{defstruct} has been declared @code{inline};

@quotation
@emph{Note}: Structures with @emph{raw} slots can currently be
stack-allocated only on x86 and x86-64. A raw slot is one
whose declared type is a subtype of exactly one of:
@code{double-float}, @code{single-float}, @code{(complex
double-float)}, @code{(complex single-float)}, or @code{sb-ext:word}; but
as an exception to the preceding, any subtype of @code{fixnum} is not
stored as raw despite also being a subtype of @code{sb-ext:word}.
@end quotation

@item otherwise-inaccessible parts of objects recognized to be dynamic
  extent. The support for detecting when this applies is very
  sophisticated. The compiler can do this detection when any value
  form for a variable contains conditional allocations, function
  calls, inlined functions, anonymous closures, or even other
  variables. This allows stack allocation of complex structures.
@end itemize

Examples:

@example
;;; Declaiming a structure constructor inline before definition makes
;;; stack allocation possible.
(declaim (inline make-thing))
(defstruct thing obj next)

;;; Stack allocation of various objects bound to DYNAMIC-EXTENT
;;; variables.
(let* ((list (list 1 2 3))
       (nested (cons (list 1 2) (list* 3 4 (list 5))))
       (vector (make-array 3 :element-type 'single-float))
       (thing (make-thing :obj list
                          :next (make-thing :obj (make-array 3))))
       (closure (let ((y ...)) (lambda () y))))
  (declare (dynamic-extent list nested vector thing closure))
  ...)

;;; Stack allocation of objects assigned to DYNAMIC-EXTENT variables.
(let ((x nil))
  (declare (dynamic-extent x))
  (setq x (list 1 2 3))
  (dotimes (i 10)
    (setq x (cons i x)))
  ...)

;;; Stack allocation of arguments to a local function is equivalent
;;; to stack allocation of local variable values.
(flet ((f (x)
         (declare (dynamic-extent x))
         ...))
  ...
  (f (list 1 2 3))
  (f (cons (cons 1 2) (cons 3 4)))
  ...)

;;; Stack allocation of &REST lists
(defun foo (&rest args)
  (declare (dynamic-extent args))
  ...)
@end example

As a notable exception to recognizing otherwise inaccessible parts
of other recognized dynamic extent values, SBCL does not as of
1.0.48.21 propagate dynamic-extentness through @code{&rest} arguments --
but another conforming implementation might, so portable code should
not rely on this.

@example
(declaim (inline foo))
(defun foo (fun &rest arguments)
  (declare (dynamic-extent arguments))
  (apply fun arguments))

(defun bar (a)
  ;; SBCL will heap allocate the result of (LIST A), and stack
  ;; allocate only the spine of the &rest list -- so this is
  ;; safe but unportable.
  ;;
  ;; Another implementation, including earlier versions of SBCL
  ;; might consider (LIST A) to be otherwise inaccessible and
  ;; stack-allocate it as well!
  (foo #'car (list a)))
@end example

If dynamic extent constraints specified in the Common Lisp standard
are violated, the best that can happen is for the program to have
garbage in variables and return values; more commonly, the system
will crash.

In particular, it is important to realize that this can interact in
suprising ways with the otherwise inaccessible parts criterion:

@example
(let* ((a (list 1 2 3))
       (b (cons a a)))
   (declare (dynamic-extent b))
   ;; Unless A is accessed elsewhere as well, SBCL will consider
   ;; it to be otherwise inaccessible -- it can only be accessed
   ;; through B, after all -- and stack allocate it as well.
   ;;
   ;; Hence returning (CAR B) here is unsafe.
   ...)
@end example

SBCL also performs sophisticated escape analysis to enable automatic
stack allocation of local functions without any bound dynamic extent
declarations in many situations where the compiler can prove that no
uses escape (traditional Lisp terminology names this situation "all
uses are downward funargs"). For example, in the following
function, the local function @code{#'predicatep} is stack allocated,
because the compiler understands that the built-in function
@code{position-if} only uses its first argument as a downward funarg:

@example
(let ((acc 0))
  (flet ((predicatep (num) (plusp (+ num off))))
    (dotimes (i 10)
      (incf acc (position-if #'predicatep array)))
    (if (plusp off)
        (incf acc (if (positivep acc) 10 3))
        (incf acc (position-if #'predicatep array))))
  acc)
@end example

Users can also declare that their own functions take downward
funargs by adding bound dynamic extent declarations on the function
arguments.

@example
(defun trivial-hof (fun arg)
  (declare (dynamic-extent fun))
  (funcall fun 3 arg))
@end example

Currently, such dynamic extent declarations only cause stack
allocation of downward funargs at call sites on sufficiently unsafe
policy. This is partly because the compiler is currently not able to
detect incorrect usage of dynamic extent declarations.

@example
(defun autodxclosure1 (&optional (x 4))
  ;; Calling a higher-order function will only implicitly
  ;; stack-allocate a funarg if the callee is trusted (a CL:
  ;; function) or the caller is unsafe.
  (declare (optimize speed (safety 0) (debug 0)))
  (trivial-hof (lambda (a b) (+ a b x)) 92))
@end example

@node modular arithmetic
@cindex modular arithmetic
@cindex arithmetic, modular
@cindex arithmetic, hardware
@section Modular Arithmetic

@menu
* Signed Modular Arithmetic: signed modular arithmetic.
@end menu

Some numeric functions have a property: n lower bits of the
result depend only on n lower bits of (all or some) arguments. If
the compiler sees an expression of form @code{(logand <expr> <mask>)},
where @code{<expr>} is a tree of such @emph{good} functions and @code{<mask>} is
known to be of type @code{(unsigned-byte <w>)}, where @code{<w>} is a @emph{good}
width, all intermediate results will be cut to @code{<w>} bits (but it is
not done for variables and constants!). This often results in an
ability to use simple machine instructions for the functions.

Consider this example:

@example
(defun i (x y)
  (declare (type (unsigned-byte 32) x y))
  (ldb (byte 32 0) (logxor x (lognot y))))
@end example

The result of @code{(lognot y)} will be negative and of type
@code{(signed-byte 33)}, so a naive implementation on a 32-bit platform
is unable to use 32-bit arithmetic here. But modular arithmetic
optimizer is able to do it: because the result is cut down to 32
bits, the compiler will replace @code{logxor} and @code{lognot} with versions
cutting results to 32 bits, and because terminals (here, expressions
@code{x} and @code{y}) are also of type @code{(unsigned-byte 32)}, 32-bit machine
arithmetic can be used.

As of SBCL 0.8.5 good functions are @code{+}, @code{-}, @code{logand}, @code{logior},
@code{logxor}, @code{lognot} and their combinations; and @code{ash} with the positive
second argument. Good widths are 32 on 32-bit CPUs and 64 on 64-bit
CPUs. While it is possible to support smaller widths as well,
currently this is not implemented.

@node signed modular arithmetic
@subsection Signed Modular Arithmetic

Sign-extending the result in the following way will be
translated into signed modular arithmetic:

@example
(defun add (a b)
  (declare (type (signed-byte 64) a b))
  (let ((u (ldb (byte 64 0) (+ a b))))
    (logior u (- (mask-field (byte 1 63) u)))))
@end example

@node recognized idioms
@cindex modular arithmetic
@cindex arithmetic, modular
@cindex arithmetic, hardware
@section Recognized Idioms

@menu
* Count Trailing Zeros: count trailing zeros.
@end menu

Common Lisp doesn't directly expose all features present in
modern hardware. Some code patterns are recognized and turned into
more efficient hardware instructions without requiring the use of
internal features.

@node count trailing zeros
@subsection Count Trailing Zeros

@example
(defun ctz (n)
  (declare (type (unsigned-byte 64) n))
  (integer-length (ldb (byte 64 0) (lognor n (- n)))))
@end example

is turned into hardware instructions on arm64 and x86-64. It returns
64 when @code{n} is 0. @code{n} can also be @code{(signed-byte 64)} or @code{fixnum}.

@node global and always bound variables
@section Global and Always-bound Variables

@anchor{Macro sb-ext defglobal}
@ffindex @sortas{defglobal sb-ext} defglobal [sb-ext]
@deffn{Macro} sb-ext:defglobal name value &optional doc
Defines @code{name} as a global variable that is always bound. @code{value} is evaluated
and assigned to @code{name} both at compile- and load-time, but only if @code{name} is not
already bound.

Global variables share their values between all threads, and cannot be
locally bound, declared special, defined as constants, and neither bound
nor defined as symbol macros.

See also the declarations @code{sb-ext:global} and @code{sb-ext:always-bound}.
@end deffn
@anchor{Declaration sb-ext global}
@ddindex @sortas{global sb-ext} global [sb-ext]
@deffn{Declaration} sb-ext:global
Syntax: @code{(sb-ext:global &rest symbols)}

Only valid as a global proclamation.

Specifies that the named symbols cannot be proclaimed or locally
declared @code{special}. Proclaiming an already special or constant variable
name as @code{sb-ext:global} signals an error. Allows more efficient value
lookup in threaded environments in addition to expressing programmer
intention.
@end deffn
@anchor{Declaration sb-ext always-bound}
@ddindex @sortas{always-bound sb-ext} always-bound [sb-ext]
@deffn{Declaration} sb-ext:always-bound
Syntax: @code{(sb-ext:always-bound &rest symbols)}

Only valid as a global proclamation.

Specifies that the named symbols are always bound. Inhibits @code{makunbound}
of the named symbols. Proclaiming an unbound symbol as
@code{sb-ext:always-bound} signals an error. Allows the compiler to elide
boundness checks from value lookups.
@end deffn
@node miscellaneous efficiency issues
@section Miscellaneous Efficiency Issues

FIXME: The material in the CMUCL manual about getting good
performance from the compiler should be reviewed, reformatted in
Texinfo, lightly edited for SBCL, and substituted into this
manual. In the meantime, the original CMUCL manual is still 95+%
correct for the SBCL version of the Python compiler. See the
sections

@itemize
@item Advanced Compiler Use and Efficiency Hints
@item Advanced Compiler Introduction
@item More About Types in Python
@item Type Inference
@item Source Optimization
@item Tail Recursion
@item Local Call
@item Block Compilation
@item Inline Expansion
@item Object Representation
@item Numbers
@item General Efficiency Hints
@item Efficiency Notes
@end itemize

Besides this information from the CMUCL manual, there are a few other
points to keep in mind.

@itemize
@item The CMUCL manual doesn't seem to state it explicitly, but Python
  has a mental block about type inference when assignment is
  involved. Python is very aggressive and clever about inferring the
  types of values bound with @code{let}, @code{let*}, inline function call, and so
  forth. However, it's much more passive and dumb about inferring
  the types of values assigned with @code{setq}, @code{setf}, and friends. It
  would be nice to fix this, but in the meantime don't expect that
  just because it's very smart about types in most respects it will
  be smart about types involved in assignments. (This doesn't affect
  its ability to benefit from explicit type declarations involving
  the assigned variables, only its ability to get by without
  explicit type declarations.)
@end itemize

@cindex garbage collector, generational
@cindex generational garbage collector
@itemize
@item Since the time the CMUCL manual was written, CMUCL (and thus SBCL)
  has gotten a generational GC. This means that there are some
  efficiency implications of various patterns of memory usage which
  aren't discussed in the CMUCL manual. (Some new material should be
  written about this.)

@item SBCL has some important known efficiency problems. Perhaps the
  most important are

@itemize
@item The garbage collector is not particularly efficient, at least
      on platforms without the generational collector (as of SBCL
      0.8.9, all except x86).

@item Various aspects of the PCL implementation of CLOS are more
      inefficient than necessary.
@end itemize
@end itemize

Finally, note that Common Lisp defines many constructs which, in the
infamous phrase, "could be compiled efficiently by a sufficiently
smart compiler". The phrase is infamous because making a compiler
which actually is sufficiently smart to find all these optimizations
systematically is well beyond the state of the art of current
compiler technology. Instead, they're optimized on a case-by-case
basis by hand-written code, or not optimized at all if the
appropriate case hasn't been hand-coded. Some cases where no such
hand-coding has been done as of SBCL version 0.6.3 include

@itemize
@item @code{(reduce #'f x)} where the type of @code{x} is known at compile time,

@item various bit vector operations, e.g. @code{(position 0 some-bit-vector)},

@item specialized sequence idioms, e.g. @code{(remove item list :count 1)},

@item cases where local compilation policy does not require excessive
  type checking, e.g. @code{(locally (declare (safety 1)) (assoc item list))}
  (which currently performs safe @code{endp} checking internal to @code{assoc}).
@end itemize

If your system's performance is suffering because of some construct
which could in principle be compiled efficiently, but which the SBCL
compiler can't in practice compile efficiently, consider writing a
patch to the compiler and submitting it for inclusion in the main
sources. Such code is often reasonably straightforward to write;
search the sources for the string @code{deftransform} to find many
examples (some straightforward, some less so).

