CLIM mail archive


Incremental Redisplay Performance

I am using CLIM 1.0 (Genera 8.1.1, CLIM 27.5) on a Symbolics 3653.

In building a CLIM UI for a graph editing application, I
found that the default incremental redisplay:

(define-application-frame ...
     (editor :application
	     :incremental-redisplay t
	     :display-after-commands t	
	     :default-text-style (parse-text-style '(:sans-serif :bold :normal))
	     :scroll-bars :both
	     :display-function 'display
	     :borders t
	     :window-class 'scaled-editor-pane-class)

  (:top-level (default-frame-top-level :prompt " "))

with -

(defmethod DISPLAY-TREE-NODES ((current-tree TREE) (pane SCALED-EDITOR-PANE-CLASS))
  "draw the tree of nodes from the root down to the leaves"
  (with-slots (time-factor root-node box-height box-width) current-tree
    (let ((half-box-height (/ box-height 2)) (half-box-width (/ box-width 2)))
      (labels ((go-down-tree (node)
		 (updating-output (pane :unique-id node :cache-test #'=
					:cache-value (node-modification-cnt node))
		   (DRAW-NODE node current-tree pane half-box-width half-box-height)
		   (let ((children (node-children node)))
		     (dotimes (i (length children))
		       (go-down-tree (aref children i)))))))
	(go-down-tree root-node)))))

for the case where I move a node and increment its node-modification-cnt from the
root down to the effected nodes -- takes about TWICE AS LONG as drawing the
entire graph from scratch.

In poking thru the stack, I found that DEFAULT-FRAME-TOP-LEVEL calls REDISPLAY-
FRAME-PANES and for each pane calls REDISPLAY with the keyword :CHECK-OVERLAPPING 
set to T, and that this overlap checking is what was taking all the time.  I do
not see any way to control that flag.  So I decided to do redisplay myself:

(define-application-frame ...
     (editor :application
	     :incremental-redisplay nil
	     :display-after-commands nil
	     :default-text-style (parse-text-style '(:sans-serif :bold :normal))
	     :scroll-bars :both
	     :borders t
	     :window-class 'scaled-editor-pane-class)

    (:top-level (lisp-listener-top-level :prompt " "))  ; from CLIM demo stuff

grab the pane output record:

	    (setf pane-output-record
		  (updating-output (pane)
		    (DISPLAY-TREE-NODES current-tree pane)))))))))

all my frame commands call my redisplay function:

  "manual redisplay of pane  & control viewport position"
  (with-slots (pane-frame pane-name pane-output-record
			  redisplay-needed-p current-tree) pane
    (when redisplay-needed-p
      (let ((msg-pane (top-level-pane pane-frame)))
	(with-reverse-video (msg-pane)
	  (write-string "Grinding ..." msg-pane)
	  (cond ((null pane-output-record)
		 (window-clear pane)
		 (with-output-recording-options (pane :draw-p nil)
		   (display pane-frame pane))
		 (window-set-viewport-position* pane 0
						(- (root-y-position current-tree)
						   (box-height current-tree)))
		 (output-recording-stream-replay pane (window-viewport pane)))
		 ;; :check-overlapping nil dramatically increases the speed of redisplay
	(setf redisplay-needed-p nil)))))
A typical redisplay using this technique takes less than a second, while the default
redisplay took about 8 seconds (for a 50 node graph).

This experience reinforces my hope that CLIM 2.0's implementation and documentation
will place more emphasis on incremental redisplay performance -- with the default 
redisplay functionality my UI was just about unusable.  With my modificaitons the 
UI demonstrates the advertised claims of CLIM.

==> Will Taylor


Main Index | Thread Index