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

@node statistical profiler
@cindex profiling, statistical
@section Statistical Profiler

The @code{sb-sprof} module, loadable by

@example
(require :sb-sprof)
@end example

provides an alternate profiler which works by taking samples of the
program execution at regular intervals, instead of instrumenting
functions as @code{sb-profile:profile} does. You might find @code{sb-sprof} more
useful than the deterministic profiler when profiling functions in the
@code{common-lisp} package, SBCL internals, or code where the instrumenting
overhead is excessive.

Additionally @code{sb-sprof} includes a limited deterministic profiler
which can be used for reporting the amounts of calls to some functions
during

@strong{Example usage:}

@example
(in-package :cl-user)

(require :sb-sprof)

(declaim (optimize speed))

(defun cpu-test-inner (a i)
  (logxor a
          (* i 5)
          (+ a i)))

(defun cpu-test (n)
  (let ((a 0))
    (dotimes (i (expt 2 n) a)
      (setf a (cpu-test-inner a i)))))

;;;; CPU profiling

;;; Take up to 1000 samples of running (CPU-TEST 26), and give a flat
;;; table report at the end. Profiling will end one the body has been
;;; evaluated once, whether or not 1000 samples have been taken.
(sb-sprof:with-profiling (:max-samples 1000
                          :report :flat
                          :loop nil)
  (cpu-test 26))

;;; Record call counts for functions defined on symbols in the CL-USER
;;; package.
(sb-sprof:profile-call-counts "CL-USER")

;;; Take 1000 samples of running (CPU-TEST 24), and give a flat
;;; table report at the end. The body will be re-evaluated in a loop
;;; until 1000 samples have been taken. A sample count will be printed
;;; after each iteration.
(sb-sprof:with-profiling (:max-samples 1000
                          :report :flat
                          :loop t
                          :show-progress t)
  (cpu-test 24))

;;;; Allocation profiling

(defun foo (&rest args)
  (mapcar (lambda (x) (float x 1d0)) args))

(defun bar (n)
  (declare (fixnum n))
  (apply #'foo (loop repeat n collect n)))

(sb-sprof:with-profiling (:max-samples 10000
                          :mode :alloc
                          :report :flat)
  (bar 1000))
@end example

@strong{Output:}

The flat report format will show a table of all functions that the
profiler encountered on the call stack during sampling, ordered by
the number of samples taken while executing that function.

@example
           Self        Total        Cumul
  Nr  Count     %  Count     %  Count     %    Calls  Function
------------------------------------------------------------------------
   1     69  24.4     97  34.3     69  24.4 67108864  CPU-TEST-INNER
   2     64  22.6     64  22.6    133  47.0        -  SB-VM::GENERIC-+
   3     39  13.8    256  90.5    172  60.8        1  CPU-TEST
   4     31  11.0     31  11.0    203  71.7        -  SB-KERNEL:TWO-ARG-XOR
@end example

For each function, the table will show three absolute and relative
sample counts. The @code{Self} column shows samples taken while directly
executing that function. The @code{Total} column shows samples taken
while executing that function or functions called from it (sampled
to a platform-specific depth). The @code{Cumul} column shows the sum of
all @code{Self} columns up to and including that line in the table.

Additionally the @code{Calls} column will record the amount of calls that
were made to the function during the profiling run. This value will
only be reported for functions that have been explicitly marked for
call counting with @code{sb-sprof:profile-call-counts}.

The profiler also hooks into the disassembler such that instructions
which have been sampled are annotated with their relative frequency
of sampling. This information is not stored across different
sampling runs.

@example
;      6CF:       702E             JO L4              ; 6/242 samples
;      6D1:       D1E3             SHL EBX, 1
;      6D3:       702A             JO L4
;      6D5: L2:   F6C303           TEST BL, 3         ; 2/242 samples
;      6D8:       756D             JNE L8
;      6DA:       8BC3             MOV EAX, EBX       ; 5/242 samples
;      6DC: L3:   83F900           CMP ECX, 0         ; 4/242 samples
@end example

@strong{Platform support}

@cindex garbage collector, generational
@cindex generational garbage collector
Allocation profiling is only supported on SBCL builds that use the
generational GC. Tracking of call stacks at a depth of more than
two levels is only supported on x86 and x86-64.

@strong{Macros}

@anchor{Macro sb-sprof with-profiling}
@ffindex @sortas{with-profiling sb-sprof} with-profiling [sb-sprof]
@deffn{Macro} sb-sprof:with-profiling (&key sample-interval alloc-interval max-samples reset mode loop max-depth show-progress threads report) &body body
Evaluate @code{body} with statistical profiling turned on. If @code{loop} is true,
loop around the @code{body} until a sufficient number of samples has been collected.
Returns the values from the last evaluation of @code{body}.

The following keyword args are recognized:

@itemize
@item @code{:sample-interval} @code{<n>}

Take a sample every <n> seconds. Default is @code{*sample-interval*}.

@item @code{:mode} @code{<mode>}

If @code{:cpu}, run the profiler in CPU profiling mode. If @code{:alloc}, run
the profiler in allocation profiling mode. If @code{:time}, run the
profiler in wallclock profiling mode.

@item @code{:max-samples} @code{<max>}

If @code{:loop} is @code{nil} (the default), collect no more than @code{<max>}
samples. If @code{:loop} is @code{t}, repeat evaluating body until @code{<max>}
samples are taken. Default is @code{*max-samples*}.

@item @code{:report} @code{<type>}

If specified, call @code{report} with @code{:type} @code{<type>} at the end.

@item @code{:reset} @code{<bool>}

If true, call @code{reset} at the beginning.

@item @code{:threads} @code{<list-form>}

Form that evaluates to the list threads to profile, or @code{:all} to
indicate that all threads should be profiled. Defaults to all
threads.

@code{:threads} has no effect on call-counting at the moment.

On some platforms (e.g. Darwin) the signals used by the profiler
are not properly delivered to threads in proportion to their CPU
usage when doing @code{:cpu} profiling. If you see empty call graphs, or
are obviously missing several samples from certain threads, you
may be falling afoul of this. In this case using @code{:mode} @code{:time} is
likely to work better.

@item @code{:loop} @code{<bool>}

If false (the default), evaluate @code{body} only once. If true
repeatedly evaluate @code{body}.
@end itemize
@end deffn
@anchor{Macro sb-sprof with-sampling}
@ffindex @sortas{with-sampling sb-sprof} with-sampling [sb-sprof]
@deffn{Macro} sb-sprof:with-sampling (&optional on) &body body
Evaluate body with statistical sampling turned on or off in the current thread.
@end deffn
@strong{Functions}

@anchor{Function sb-sprof map-traces}
@ffindex @sortas{map-traces sb-sprof} map-traces [sb-sprof]
@deffn{Function} sb-sprof:map-traces function samples
Call @code{function} on each trace in @code{samples}

The signature of @code{function} must be compatible with (thread trace).

@code{function} is called once for each trace where @code{thread} is the
@code{sb-thread:thread} instance that was sampled to produce @code{trace}, and @code{trace}
is an opaque object to be passed to @code{map-trace-pc-locs}.

EXPERIMENTAL: Interface subject to change.
@end deffn
@anchor{Function sb-sprof sample-pc}
@ffindex @sortas{sample-pc sb-sprof} sample-pc [sb-sprof]
@deffn{Function} sb-sprof:sample-pc info pc-or-offset
Extract and return program counter from @code{info} and @code{pc-or-offset}.

Can be applied to the arguments passed by @code{map-trace-pc-locs} and
@code{map-all-pc-locs}.

EXPERIMENTAL: Interface subject to change.
@end deffn
@anchor{Function sb-sprof report}
@ffindex @sortas{report sb-sprof} report [sb-sprof]
@deffn{Function} sb-sprof:report &key type max min-percent call-graph sort-by sort-order stream show-progress
Report statistical profiling results.  The following keyword
   args are recognized:

@itemize
@item @code{:type} @code{<type>}

Specifies the type of report to generate. If @code{:flat}, show flat
report, if @code{:graph} show a call graph and a flat report. If nil,
don't print out a report.

@item @code{:stream} @code{<stream>}

Specify a stream to print the report on.  Default is
@code{*standard-output*}.

@item @code{:max} @code{<max>}

Don't show more than @code{<max>} entries in the flat report.

@item @code{:min-percent} @code{<min-percent>}

Don't show functions taking less than @code{<min-percent>} of the
total time in the flat report.

@item @code{:sort-by} @code{<column>}

If @code{:samples}, sort flat report by number of samples taken.
If @code{:cumulative-samples}, sort flat report by cumulative number of samples
taken (shows how much time each function spent on stack.) Default
is @code{*report-sort-by*}.

@item @code{:sort-order} @code{<order>}

If @code{:descending}, sort flat report in descending order. If @code{:ascending},
sort flat report in ascending order. Default is @code{*report-sort-order*}.

@item @code{:show-progress} @code{<bool>}

     If true, print progress messages while generating the call graph.

@item @code{:call-graph} @code{<graph>}

     Print a report from @code{<graph>} instead of the latest profiling
     results.
@end itemize

Value of this function is a @code{call-graph} object representing the
resulting call-graph, or @code{nil} if there are no samples (e.g. right after
calling @code{reset}.)

Profiling is stopped before the call graph is generated.
@end deffn
@anchor{Function sb-sprof reset}
@ffindex @sortas{reset sb-sprof} reset [sb-sprof]
@deffn{Function} sb-sprof:reset
Reset the profiler.
@end deffn
@anchor{Function sb-sprof start-profiling}
@ffindex @sortas{start-profiling sb-sprof} start-profiling [sb-sprof]
@deffn{Function} sb-sprof:start-profiling &key max-samples mode sample-interval alloc-interval max-depth threads
Start profiling statistically in the current thread if not already profiling.
The following keyword args are recognized:

@itemize
@item @code{:sample-interval} @code{<n>}

Take a sample every @code{<n>} seconds. Default is @code{*sample-interval*}.

@item @code{:mode} @code{<mode>}

If @code{:cpu}, run the profiler in CPU profiling mode. If @code{:alloc}, run
the profiler in allocation profiling mode. If @code{:time}, run the
profiler in wallclock profiling mode.

@item @code{:max-samples} @code{<max>}

Maximum number of stack traces to collect. Default is
@code{*max-samples*}.

@item @code{:threads} @code{<list>}

List threads to profile, or @code{:all} to indicate that all threads
should be profiled. Defaults to @code{:all}.

@code{:threads} has no effect on call-counting at the moment.

On some platforms (e.g. Darwin) the signals used by the profiler
are not properly delivered to threads in proportion to their CPU
usage when doing @code{:cpu} profiling. If you see empty call graphs, or
are obviously missing several samples from certain threads, you
may be falling afoul of this.
@end itemize
@end deffn
@anchor{Function sb-sprof stop-profiling}
@ffindex @sortas{stop-profiling sb-sprof} stop-profiling [sb-sprof]
@deffn{Function} sb-sprof:stop-profiling
Stop profiling if profiling.
@end deffn
@anchor{Function sb-sprof profile-call-counts}
@ffindex @sortas{profile-call-counts sb-sprof} profile-call-counts [sb-sprof]
@deffn{Function} sb-sprof:profile-call-counts &rest names
Mark the functions named by @code{names} as being subject to call counting
during statistical profiling. If a string is used as a name, it will
be interpreted as a package name. In this case call counting will be
done for all functions with names like @code{x} or @code{(setf x)}, where @code{x} is
a symbol with the package as its home package.
@end deffn
@anchor{Function sb-sprof unprofile-call-counts}
@ffindex @sortas{unprofile-call-counts sb-sprof} unprofile-call-counts [sb-sprof]
@deffn{Function} sb-sprof:unprofile-call-counts
Clear all call counting information. Call counting will be done for no
functions during statistical profiling.
@end deffn
@strong{Variables}

@anchor{Variable sb-sprof *max-samples*}
@vvindex @sortas{max-samples* sb-sprof} *max-samples* [sb-sprof]
@deffn{Variable} sb-sprof:*max-samples*
Default maximum number of stack traces collected.
@end deffn
@anchor{Variable sb-sprof *sample-interval*}
@vvindex @sortas{sample-interval* sb-sprof} *sample-interval* [sb-sprof]
@deffn{Variable} sb-sprof:*sample-interval*
Default number of seconds between samples.
@end deffn
@strong{Credits}

@code{sb-sprof} is an SBCL port, with enhancements, of Gerd Moellmann's
statistical profiler for CMUCL.

