3 (defvar *periodic-profilers
* (make-hash-table))
5 (defstruct (periodic-profiler (:conc-name periodic-profiler-
)
6 (:print-object print-periodic-profiler
))
12 (last-profile-style nil
))
14 (defun print-periodic-profiler (object stream
)
15 (print-unreadable-object (object stream
:type t
:identity t
)
16 (format stream
"~a every ~a"
17 (periodic-profiler-function object
)
18 (periodic-profiler-period object
))))
20 (excl:def-fwrapper profile-this-periodically
(&rest args
)
21 (declare (ignorable args
)
22 (dynamic-extent args
))
23 (let* ((spot (%find-periodic-profile-spot excl
::primary-function
))
25 (if (> (- (get-universal-time) (periodic-profiler-last-active pp
))
26 (periodic-profiler-period pp
))
27 (let* ((style (periodic-profiler-profile-style pp
)))
28 (setf (periodic-profiler-last-profile-style pp
)
29 (if (eq style
:alternating
)
30 (case (periodic-profiler-last-profile-style pp
)
35 ((periodic-profiler-report-name pp
)
36 (periodic-profiler-last-profile-style pp
))
37 (excl:call-next-fwrapper
))
38 (setf (periodic-profiler-last-active pp
) (get-universal-time)))
39 (excl:call-next-fwrapper
))))
41 (defun start-periodic-profiling (report-name function
&key
(period 10)
42 (profile-style :time
))
43 (assert (find profile-style
'(:time
:space
:alternating
)))
44 (let ((spot (%find-periodic-profile-spot function
)))
45 (setf (first spot
) (make-periodic-profiler
46 :report-name report-name
49 :profile-style profile-style
)
52 :periodic-profiler
'profile-this-periodically
)))
54 (defun stop-periodic-profiling (function)
55 (setf (second (%find-periodic-profile-spot function
)) nil
)
56 (excl:funwrap function
:periodic-profiler
))
58 (defun %find-periodic-profile-spot
(function)
59 (setf function
(coerce function
'function
))
60 (multiple-value-bind (spot found?
)
61 (gethash function
*periodic-profilers
*)
64 (setf (gethash function
*periodic-profilers
*)
67 (defun periodic-profilers ()
69 (maphash (lambda (k v
)
71 (when (and (consp v
) (second v
))
73 (push (list (periodic-profiler-function pp
)
74 (periodic-profiler-period pp
)
75 (periodic-profiler-profile-style pp
))
86 (while-counting-events (0.5
)
87 (loop for i from
0 do
(setf x i
)))
92 (with-profile-report ('test-pp
:time
) (test-pp))
95 (start-periodic-profiling
96 'test-pp
'test-pp
:period
1.5 :profile-style
:alternating
)
98 (stop-periodic-profiling