[slime-devel] Debugger slowness is killing me ...

Peter Seibel peter at javamonkey.com
Wed Sep 15 21:19:06 UTC 2004


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

-- 
Peter Seibel                                      peter at javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp





More information about the slime-devel mailing list