diff --git a/NEWS b/NEWS index 07aac9faad..3ef32c4a48 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ changes relative to sbcl-1.4.5: * enhancement: DISASSEMBLE on a symbol naming a macro will disassemble the expander, not the code that traps attempted FUNCALL of the macro. + * enhancement: The sb-sprof contrib now provides an experimental interface + for accessing collected profiler data. changes in sbcl-1.4.5 relative to sbcl-1.4.4: * minor incompatible change: building with/without the :sb-package-locks diff --git a/contrib/sb-sprof/package.lisp b/contrib/sb-sprof/package.lisp index 694ed7126f..6c87e08806 100644 --- a/contrib/sb-sprof/package.lisp +++ b/contrib/sb-sprof/package.lisp @@ -8,6 +8,7 @@ (:export ;; Recording #:start-sampling #:stop-sampling #:with-sampling + #:map-traces #:map-trace-samples #:map-all-samples ;; Call counting #:profile-call-counts #:unprofile-call-counts diff --git a/contrib/sb-sprof/record.lisp b/contrib/sb-sprof/record.lisp index 88cef51cfd..697764c903 100644 --- a/contrib/sb-sprof/record.lisp +++ b/contrib/sb-sprof/record.lisp @@ -81,7 +81,67 @@ (setf (aref vector index) info (aref vector (1+ index)) pc-or-offset) (setf (samples-index samples) (+ index 2)))) + +;;; Trace and sample and access functions + +(defun map-traces (function samples) + "Call FUNCTION on each trace in SAMPLES + +The lambda list of FUNCTION has to be compatible to + + (trace) + +. FUNCTION is called once for each trace such that TRACE is an opaque +object whose only purpose is being used as the second argument to +MAP-CALLS. + +EXPERIMENTAL: Interface subject to change." + (let ((function (sb-kernel:%coerce-callable-to-fun function)) + (vector (samples-vector samples)) + (index (samples-index samples))) + (sb-int:aver (eq (aref vector 0) 'trace-start)) + (loop for start = 0 then end + while (< start index) + for end = (or (position 'trace-start vector :start (+ start 1)) + index) + do (let ((trace (list vector start end))) + (funcall function trace))))) + +(defun map-trace-samples (function trace) + "Call FUNCTION on each sample in TRACE. + +The lambda list of FUNCTION has to be compatible to + + (info pc-or-offset) + +. + +TRACE is an object as received by a function passed to MAP-TRACES. + +EXPERIMENTAL: Interface subject to change." + (let ((function (sb-kernel:%coerce-callable-to-fun function))) + (destructuring-bind (samples start end) trace + (loop for i from (- end 2) downto (+ start 2) by 2 + for info = (aref samples i) + for pc-or-offset = (aref samples (1+ i)) + do (funcall function info pc-or-offset))))) + +(declaim (special *samples*)) +(defun map-all-samples (function &optional (samples *samples*)) + "Call FUNCTION on each sample in SAMPLES. + +The lambda list of FUNCTION has to be compatible to + + (info pc-or-offset) + +. + +SAMPLES is usually the value of *SAMPLES* after a profiling run. +EXPERIMENTAL: Interface subject to change." + (sb-int:dx-flet ((do-trace (trace) + (map-trace-samples function trace))) + (map-traces #'do-trace samples))) ;;; Sampling diff --git a/contrib/sb-sprof/sb-sprof.texinfo b/contrib/sb-sprof/sb-sprof.texinfo index be4298ae37..0f790c2596 100644 --- a/contrib/sb-sprof/sb-sprof.texinfo +++ b/contrib/sb-sprof/sb-sprof.texinfo @@ -135,6 +135,12 @@ depth of more than two levels is only supported on x86 and x86-64. @subsection Functions +@include fun-sb-sprof-map-traces.texinfo + +@include fun-sb-sprof-map-trace-samples.texinfo + +@include fun-sb-sprof-map-all-samples.texinfo + @include fun-sb-sprof-report.texinfo @include fun-sb-sprof-reset.texinfo