CLIM mail archive
[Prev][Next][Index][Thread]
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:
(defmethod REDISPLAY-PANE ((pane EDITOR-PANE-MIXIN))
"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)))
(t
;; :check-overlapping nil dramatically increases the speed of redisplay
(REDISPLAY PANE-OUTPUT-RECORD PANE :CHECK-OVERLAPPING NIL))))
(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
Follow-Ups:
Main Index |
Thread Index