CLIM mail archive
[Prev][Next][Index][Thread]
consing results
Thanks to messages from John Aspinall and Scott McKay, I learned that my key
problem was that output recording was on. Turning it off improved matters a
lot. Furthermore, Scott McKay suggested using the MEDIUM-DRAW functions, which
helped, too. Unfortunately, MEDIUM-DRAW-ARROW doesn't exist, so a direct
comparison for that isn't possible. Here are the final results:
Original Consing (output recording on)
draw-ellipse* => 361 words
draw-line* => 158 words
draw-arrow* => 607 words
Consing with output recording off, using
(with-output-recording-options (pane :record nil :draw t) ...)
draw-ellipse* => 98 words
draw-line* => 56 words
draw-arrow* => 326 words
Consing with output recording off, and using medium functions:
medium-draw-ellipse* => 58 words
medium-draw-line* => 26 words
These results are for CLIM 2.0 in Lucid on a SPARC. Your mileage may vary.
It would be nice if the functions didn't cons at all, but this is a great
improvement, and I appreciate the help.
What do I give up by using MEDIUM-DRAW- functions instead of the higher-level
drawing functions? It seems that all I give up is keyword arguments for things
like ink, which instead have to be done by WITH-DRAWING-OPTIONS. Anything else?
Scott D. Anderson
anderson@cs.umass.edu
;;; ============================================================================
;;; The following is the code to reproduce the results above.
(in-package :clim-user)
(define-application-frame cons-frame ()
()
(:panes
(menu :command-menu)
(display :application
:window-class 'display-window
:incremental-redisplay nil
:display-function 'draw-display-pane)))
;;; The following methods are irrelevant to the bug.
(defmethod frame-standard-input ((frame cons-frame)) *terminal-io*)
(defmethod frame-standard-output ((frame cons-frame)) *terminal-io*)
(defmethod draw-display-pane ((application cons-frame) stream)
(window-clear stream))
(define-cons-frame-command (com-exit :menu T) ()
(frame-exit *application-frame*))
;;; ============================================================================
;;; The following is a macro to find out how much something conses.
(defmacro consing (&body body)
"Executes `body' in a way that allows consing to be measured. Returns the
number of words consed.
This uses lcl:gc-size, as shown on page 5-33 of the Lucid User's Manual.
Ephemeral GC is turned off at the beginning, if necessary, and returned to its
original state afterwards. See the functions egc-off and egc-on.
Known bugs: This macro will return weird results if a GC occurs during the
body. It seems too risky to turn off GC. This macro is best used in the body
of a compiled function, as the examples above were."
(let ((gc-on? (gensym))
(isize (gensym))
(conses (gensym)))
`(let ((,gc-on? (lcl:egc-state)))
(if ,gc-on? (lcl:egc-off))
(let ((,isize (lcl:gc-size)) ,conses)
(unwind-protect (progn ,@body)
(setf ,conses (floor (- (lcl:gc-size) ,isize) 4))
(if ,gc-on? (lcl:egc-on)))
,conses))))
;;; ============================================================================
;;; Consing is exhibited by the following command:
(define-cons-frame-command (com-test-consing :menu t) ()
(let ((pane (get-frame-pane *application-frame* 'display))
(times 100))
(multiple-value-bind (w h) (window-inside-size pane)
(setf w (round w 2)
h (round h 2))
(format t "~2&Consing with output recording.~%")
(let ((words (consing
(loop repeat times do
(draw-ellipse* pane w h 50 0 0 50 :ink +flipping-ink+)))))
(format t "~&~d words consed, or about ~f words per call to draw-ellipse*.~%"
words (/ words times)))
(let ((words (consing
(loop repeat times do
(draw-line* pane 0 0 w h :ink +flipping-ink+)))))
(format t "~&~d words consed, or about ~f words per call to draw-line*.~%"
words (/ words times)))
(let ((words (consing
(loop repeat times do
(draw-arrow* pane 0 0 w h :ink +flipping-ink+)))))
(format t "~&~d words consed, or about ~f words per call to draw-arrow*.~%"
words (/ words times))))))
(define-cons-frame-command (com-test-consing-no-recording :menu t) ()
(let ((pane (get-frame-pane *application-frame* 'display))
(times 100))
(multiple-value-bind (w h) (window-inside-size pane)
(setf w (round w 2)
h (round h 2))
(format t "~2&Consing with no output recording.~%")
(let ((words (consing
(with-output-recording-options (pane :record nil :draw t)
(loop repeat times do
(draw-ellipse* pane w h 50 0 0 50 :ink +flipping-ink+))))))
(format t "~&~d words consed, or about ~f words per call to draw-ellipse*.~%"
words (/ words times)))
(let ((words (consing
(with-output-recording-options (pane :record nil :draw t)
(loop repeat times do
(draw-line* pane 0 0 w h :ink +flipping-ink+))))))
(format t "~&~d words consed, or about ~f words per call to draw-line*.~%"
words (/ words times)))
(let ((words (consing
(with-output-recording-options (pane :record nil :draw t)
(loop repeat times do
(draw-arrow* pane 0 0 w h :ink +flipping-ink+))))))
(format t "~&~d words consed, or about ~f words per call to draw-arrow*.~%"
words (/ words times))))))
(define-cons-frame-command (com-test-medium-consing :menu t) ()
(let ((pane (get-frame-pane *application-frame* 'display))
(times 100))
(multiple-value-bind (w h) (window-inside-size pane)
(setf w (round w 2)
h (round h 2))
(format t "~2&MEDIUM-DRAW consing with no output recording.~%")
(let ((words (consing
(with-output-recording-options (pane :record nil :draw t)
(with-drawing-options (pane :ink +flipping-ink+)
(loop repeat times do
(medium-draw-ellipse* pane w h 50 0 0 50 0 clim-utils:2pi t)))))))
(format t "~&~d words consed, or about ~f words per call to medium-draw-ellipse*.~%"
words (/ words times)))
(let ((words (consing
(with-output-recording-options (pane :record nil :draw t)
(with-drawing-options (pane :ink +flipping-ink+)
(loop repeat times do
(medium-draw-line* pane 0 0 w h)))))))
(format t "~&~d words consed, or about ~f words per call to medium-draw-line*.~%"
words (/ words times)))
)))
;;; ============================================================================
(defvar *cons-frame* nil)
;;; Call this in the lisp listener
(defun doit ()
(setf *cons-frame* (make-application-frame 'cons-frame))
(run-frame-top-level *cons-frame*))
;Get the following output:
;> (doit)
;Consing with output recording.
;36142 words consed, or about 361.42 words per call to draw-ellipse*.
;15808 words consed, or about 158.08 words per call to draw-line*.
;60752 words consed, or about 607.52 words per call to draw-arrow*.
;Consing with no output recording.
;9814 words consed, or about 98.14 words per call to draw-ellipse*.
;5618 words consed, or about 56.18 words per call to draw-line*.
;32634 words consed, or about 326.34 words per call to draw-arrow*.
;MEDIUM-DRAW consing with no output recording.
;5840 words consed, or about 58.4 words per call to medium-draw-ellipse*.
;2640 words consed, or about 26.4 words per call to medium-draw-line*.
;NIL
;>
Follow-Ups:
Main Index |
Thread Index