3 (eval-when (:compile-toplevel
)
4 (declaim (optimize (speed 3) (safety 1))))
6 (defmacro with-measuring
((var measure-fn
) &body body
)
7 (let ((initial (gensym)))
8 `(let ((,initial
(,measure-fn
)))
10 (setf ,var
(- (,measure-fn
) ,initial
)))))
12 (defmacro measure-time
((var) &body body
)
14 (with-measuring (,var get-internal-real-time
)
16 (setf ,var
(coerce (/ ,var internal-time-units-per-second
)
19 (defmacro measure-conses
((var) &body body
)
20 `(with-measuring (,var total-bytes-allocated
)
23 (defun measure-fn (fn &rest args
)
24 (declare (dynamic-extent args
))
25 (let ((bytes 0) (seconds 0) result
)
26 (measure-time (seconds)
27 (measure-conses (bytes)
28 (setf result
(apply fn args
))))
29 (values seconds bytes result
)))
31 (defmacro measure
(seconds bytes
&body body
)
32 (let ((result (gensym)))
34 (measure-time (,seconds
)
35 (measure-conses (,bytes
)
36 (setf ,result
(progn ,@body
))))
39 (defmacro measure-time-and-conses
(&body body
)
40 (let ((seconds (gensym))
43 `(let ((,seconds
0) (,conses
0) ,results
)
44 (setf ,results
(multiple-value-list
45 (measure ,seconds
,conses
,@body
)))
46 (values-list (nconc (list ,seconds
,conses
)
50 ;; tries to handle multiple values (but fails since measure doesn't)
51 (defmacro measure-time-and-conses
(&body body
)
52 (let ((seconds (gensym))
54 `(let ((,seconds
0) (,conses
0))
55 (values-list (nconc (multiple-value-list
56 (measure ,seconds
,conses
,@body
))
57 (list ,seconds
,conses
))))))
59 (defparameter *benchmark-file
*
60 (asdf:system-relative-pathname
61 'lift
"benchmark-data/benchmarks.log"))
63 (defvar *collect-call-counts
* nil
)
65 (defvar *additional-markers
* nil
)
67 (defvar *profiling-threshold
* nil
)
70 (defun cancel-current-profile (&key force?
)
71 (when (prof::current-profile-actual prof
::*current-profile
*)
73 (assert (member (prof:profiler-status
) '(:inactive
))))
75 (setf prof
::*current-profile
* (prof::make-current-profile
))))
78 (defun current-profile-sample-count ()
79 (ecase (prof::profiler-status
:verbose nil
)
80 ((:inactive
:analyzed
) 0)
82 (slot-value (prof::current-profile-actual prof
::*current-profile
*)
84 (:sampling
(warn "Can't determine count while sampling"))))
86 ;; FIXME -- functionify this!
88 (defmacro with-profile-report
((name style
&key
(log-name *benchmark-file
*)
89 (call-counts-p *collect-call-counts
*))
91 (assert (member style
'(:time
:space
)))
92 `(let ((seconds 0.0) (conses 0) result
)
93 (cancel-current-profile :force? t
)
95 (prof:with-profiling
(:type
,style
:count
,call-counts-p
)
96 (measure seconds conses
,@body
))
97 (ensure-directories-exist ,log-name
)
99 (with-open-file (output ,log-name
101 :if-does-not-exist
:create
103 (with-standard-io-syntax
104 (let ((*print-readably
* nil
))
106 (format output
"\(~11,d ~20,s ~10,s ~10,s ~{~s~^ ~} ~s\)"
107 (date-stamp :include-time? t
) ,name
108 seconds conses
*additional-markers
*
110 (when (> (current-profile-sample-count) 0)
111 (let ((pathname (unique-filename
115 :name
(format nil
"~a-~a-" ,name
,style
))
117 (let ((prof:*significance-threshold
*
118 (or *profiling-threshold
* 0.01)))
119 (format t
"~&Profiling output being sent to ~a" pathname
)
120 (with-open-file (output pathname
122 :if-does-not-exist
:create
124 (format output
"~&Profile data for ~a" ,name
)
125 (format output
"~&Date: ~a"
126 (excl:locale-print-time
(get-universal-time)
127 :fmt
"%B %d, %Y %T" :stream nil
))
128 (format output
"~& Total time: ~,2F; Total space: ~:d \(~:*~d\)"
130 (format output
"~%~%")
131 (when (or (eq :time
,style
)
133 (prof:show-flat-profile
:stream output
)
134 (prof:show-call-graph
:stream output
)
136 (format output
"~%~%Call counts~%")
137 (let ((*standard-output
* output
))
138 (prof:show-call-counts
)))))))))))
141 ;; integrate with LIFT
143 (pushnew :measure
*deftest-clauses
*)
146 :measure
1 :class-def
147 (lambda () (def :measure
))
148 '((setf (def :measure
) (cleanup-parsed-parameter value
)))
150 (pushnew 'measured-test-mixin
(def :superclasses
))
153 (defclass measured-test-mixin
()
154 ((total-conses :initform
0
155 :accessor total-conses
)
156 (total-seconds :initform
0
157 :accessor total-seconds
)))
162 (defun test-sleep (period)
163 (print (get-universal-time))
165 (mp:process-wait-with-timeout
166 "wait-for-delay" period
168 (sleep (1+ period
)))))
169 (print (get-universal-time)))
177 (defun test-gates (period)
178 (print (get-universal-time))
179 (let ((g (mp:make-gate nil
)))
181 (mp:process-wait-with-timeout
182 "wait-for-delay" period
184 (mp:gate-open-p gate
))
186 (print (get-universal-time)))
199 (princ "ls" (shell-session-input-stream *ss
*))
200 (terpri (shell-session-input-stream *ss
*))
201 (force-output (shell-session-input-stream *ss
*))
203 (read-shell-session-stream *ss
* :output
)
205 (shell-session-command *ss
* "ls")
207 (shell-session-command *ss
* "ps u")
209 (end-shell-session *ss
*)
211 (compile 'read-from-stream-no-hang
)
213 (with-input-from-string (s "hello there")
214 (read-from-stream-no-hang s
))
216 (read-shell-session-stream *ss
* :output
)
218 (setf *ss
* (make-shell-session))
220 (count-repetitions-in-period
222 (shell-session-command *ss
* "ps u"))
225 (count-repetitions-in-period
227 (selected-metatilities::os-processes
))