I seem to keep doing things that drop me into the debugger with really long error messages. The amount of time it takes for the debugger to return (in Allegro anyway) seems to be proportional to the length of the output that has to be displayed in the *sldb* buffer. It can take many, many tens of seconds before the *sldb* shows up. In the meantime I have no idea what the heck is going on. To get a sense of what's happening try this:
CL-USER> (defparameter *c* (make-condition 'simple-error :format-control "foo: ~a" :format-arguments (list (loop for i from 1 to 100000 collect i))))
*C*
Then do this, hitting '0' as soon as you see the *sldb* buffer:
CL-USER> (time (with-simple-restart (abort "Bail!") (error *c*)))
I got:
; cpu time (non-gc) 750 msec user, 10 msec system ; cpu time (gc) 0 msec user, 0 msec system ; cpu time (total) 750 msec user, 10 msec system ; real time 8,289 msec ; space allocation: ; 805 cons cells, 2,463,904 other bytes, 0 static bytes NIL T
The I redefined format-sldb-condition in swank-allegro.lisp from:
(defimplementation format-sldb-condition (c) (princ-to-string c))
to this:
(defimplementation format-sldb-condition (c) (let ((str (princ-to-string c))) (if (> (length str) 256) (format nil "~a ..." (subseq str 0 256)) str)))
Now I try again:
CL-USER> (time (with-simple-restart (abort "Bail!") (error *c*))) ; cpu time (non-gc) 630 msec user, 0 msec system ; cpu time (gc) 0 msec user, 0 msec system ; cpu time (total) 630 msec user, 0 msec system ; real time 1,102 msec ; space allocation: ; 756 cons cells, 1,269,984 other bytes, 0 static bytes NIL T
~8x faster. I don't think the condition is the only thing that matters. For instance the stack frames can also be quite long. (If you inline the call to MAKE-CONDITION rather than passing a parameter to ERROR it will also be quite slow, even with my change.)
However I'm not sure if there's a good principled way to deal with this--it seems the ideal thing would be for SWANK to somehow keep more of the information on its side and send Emacs just enough to display the buffer while allowing emacs to request more information later. For example, we could stash the condition object somewhere on the connection and send emacs an abbreviated version. Then we could provide a keybinding in the *sldb* buffer that causes emacs to send a message to SWANK saying, send me the full condition now which would then be put in the appropriate place in the buffer.
Or is that crazy? If not, if someone was feeling really ambitious, maybe this could be developed into a general facility--provide a way for SWANK to send emacs an object that contains a short string and an id which emacs can then use to request a more elaborate string representation. Then on the emacs side provide a function to insert such an object into a buffer with appropriate overlays or properties or whatever to make the short string "live" so clicking on it or hitting a key while the cursor is in it causes emacs to replace it with the longer version.
-Peter