Subject: Re: bug#15555: 24.3; Bidirectional display very slow with long lines

From: Eli Zaretskii <[email-masked]>
Date: Tue, 18 Feb 2014 19:42:41 +0200

> Date: Tue, 18 Feb 2014 16:43:52 +0400
> From: Dmitry Antipov <[email-masked]>
> CC: [email-masked]
> 
> Hm... I have two files, with 2000 and 4000 first chars extracted from the beginning
> of the monster string from http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15555#5.
> 
> The following function:
> 
> (defun bug15555 ()
>    (interactive)
>    (while (not (eobp))
>      (right-char 1)
>      (redisplay)
>      (sleep-for 0.01)))
> 
> runs smoothly over 2000.txt, but painfully slow over 4000.txt.

I'm not sure I can reproduce this.  Is it possible that the difference
you see between the speed of moving the cursor in these the two files
is due solely to the fact that the smaller file fits completely in the
window, while the larger file does not?  IOW, if you enlarge the
window such that the larger file is visible in its entirety, don't you
see the same speed as with the smaller file?  (I need about 52 lines
of text in the window to show the whole of the file 4000.txt.)

Likewise if you insert a R2L character at the beginning of 4000.txt,
thus making its paragraph take the R2L base direction: now the cursor
motion is fast even if the display needs to scroll to keep point
visible, i.e. with the original window size you get in "emacs -Q".

Also, the cursor movement is quite fast, and uses about 8% of a single
execution unit of my Core i7, until the first time it needs to go
outside the visible portion of the buffer, at which point the CPU
usage of that single execution unit soars to almost 80%.

If you see something different, please describe what you see.

If you see what I described above, then this is a known (to me ;-)
problem: when we have a continued line that takes more than 2 screen
lines, and that line consists of mostly R2L characters, but the
paragraph direction is L2R (or vice versa), then redisplay sometimes
infloops when it needs to scroll the text in the window.  The loop is
not on the C level, it just causes a continuous series of re-entering
redisplay, so you can stop this "infloop" by some radical cursor
motion command, like C-v.

This problem is hard to solve, because the code which finds a suitable
window-start intrinsically assumes that the window-start position is
always at column zero of the window, which is false with bidirectional
text.  Some of the code that is related to this needs to be redesigned
to avoid this assumption.  I hope to get to this some day, but since
this situation is quite rare (paragraphs full of R2L characters
normally have R2L base direction), this problem was never high on my
todo list.

> The latter case also shows the very pathological profile with ~25%
> CPU spent in memcpy.
> 
> Are you sure that bidi_copy_it doesn't add one more bottleneck to the whole
> stuff?

No, I don't think it does.  But doing that in an infloop might ;-)

Anyway, just moving cursor horizontally cannot possibly be slow due to
bidi, especially as long as point stays in the same screenful.  The
redisplay becomes unbearably slow with long lines only when you either
scroll the display (e.g., C-v) or for vertical cursor motion, because
these require the display engine to traverse many buffer positions,
many more than is needed to just move the cursor, and it currently can
only start that traversal from the beginning of a physical line.