"Kirill 'Big K' Katsnelson" <kkm(a)dtmx.com> writes:
> Expand minibuffer so that it is a few lines long.
> Execute (signal-error 'error (make-list 1000 t))
>
> For me, the list of t's is printed into the minibuffer as if it was
> a plain old 1200 baud terminal, then XEmacs stalls for ~3 sec, with
> GC cursor(?) flashing every second, 3-4 times. Increasing the length
> from 1000 to 1500 makes this happen 6-8 times. The relation seems to
> be quadratic or worse.
I understand that code -- the plain `message' had the same problem,
and I fixed it, with phone help from Ben. Basically the problem is
that `error' repeatedly updates the echo area, which has at least two
bad consequences.
The code in question is in print_error_message(), the "Default method"
part, the `while (!NILP (tail)) { ... }' part. The two bad
consequences are:
* print_internal() is called with STREAM, which is in this case the
echo area. The echo area is updated immediately due to its nature.
It would be nice if that code could somehow delay the echo area
update.
* The garbage collections you see are due to `append-message' (called
by echo_area_append()) trying to keep the top of the message-stack
in sync with the contents of the "*Echo Area*" buffer. So what
happens is that these strings are created in succession:
"t"
"t: "
"t: t"
"t: t, "
"t: t, t"
...
When this happens many times with each string longer than the last
one, it turns into a GC frenzy. This is all explained in my comment
in print_prepare().
The fix that addresses both problem is to avoid direct printing to
minibuffer altogether: instead, the code prints into a temporary
resizing buffer stream. When the printing is done, the stream
contents are dumped into minibuffer. This is how all high-level
printing functions work -- except for Fdisplay_error.
Given that the infrastructure (kludge) for doing this already exists
in print_prepare(), the only fix needed is for print_error_message()
to call print_prepare().
For me, this patch fixes the problem -- the printing is fast with
1000-element, 10000-element, etc. lists. Please let me know if it
works for you.
2000-01-14 Hrvoje Niksic <hniksic(a)iskon.hr>
* print.c (print_error_message): Call print_prepare().
--- src/print.c.orig Fri Jan 14 09:27:59 2000
+++ src/print.c Fri Jan 14 09:38:38 2000
@@ -627,8 +627,13 @@
{
int first = 1;
int speccount = specpdl_depth ();
+ Lisp_Object frame = Qnil;
+ struct gcpro gcpro1;
+ GCPRO1 (stream);
specbind (Qprint_message_label, Qerror);
+ stream = print_prepare (stream, &frame);
+
tail = Fcdr (error_object);
if (EQ (type, Qerror))
{
@@ -650,6 +655,8 @@
tail = Fcdr (tail);
first = 0;
}
+ print_finish (stream, frame);
+ UNGCPRO;
unbind_to (speccount, Qnil);
return;
/* not reached */