GNU bug report logs -
#78766
100-4000x redisplay slowdown with vscroll>0 and make-cursor-line-fully-visible=t
Previous Next
Full log
Message #11 received at 78766 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
> On Jun 12, 2025, at 2:01 AM, Eli Zaretskii <eliz <at> gnu.org> wrote:
Thanks for taking a look.
> AFAIU, you are asking Emacs to do the impossible: make the cursor line
> fully-visible when the cursor line is at the top of the window, and
> therefore _cannot_ be fully visible due to non-zero vscroll. Am I
> right, or did I miss something?
> If I'm right, then could you please explain what do you expect in this
> situation, and why do you expect this to do anything useful?
Other than the extreme slowness, the current behavior with make-cursor-line-fully-visible=t is fine. Commands which move window-start check for partially visible cursor lines (at the bottom of the window) and make them fully visible, presumably by zeroing vscroll and changing window-start. Other point movement commands do nothing special. I do note that line-move as a special case usually resets vscroll to zero, which quickly relieves the issue.
> I haven't yet step through the code in this case, but my guess is that
> the display engine attempts all kinds of measures to make the cursor
> line visible, eventually failing, and those attempts are expensive
> because the display code was never designed to cope with such a
> strange set of conflicting requirements. In particular, it expects
> the partially-visible line situation to happen at the bottom of the
> window, not at its top.
Interesting. If there's not a straightforward way to avoid these expensive (and doomed to fail) attempts, perhaps a means of preventing the cursor from landing on a partially visible top line would be a better approach. Or even forcibly disabling the checks when point is on the first line of the window, and updating the docs to mention `make-cursor-line-fully-visible=t' works only on the final line.
> We could perhaps improve
> the situation in some way, but I need to understand why such a strange
> combination of display-related knobs is used in the first place, and
> what do you expect it to produce and why.
This reproduction is not of course meant to be a realistic code path, it's merely a straightforward way to reliably demonstrate the issue. The situation of a cursor landing on a partially visible top line can happen naturally whenever vscroll>0 in a window. Non-zero vscroll is used by pixel scrolling, but also by line-move with tall lines (e.g. images).
Point ends up on a partial first line for a variety of reasons. For example, it happens reliably when folding (hiding) an org-mode block which occupies the full window height in a separate window on the frame. Check the ultra-scroll issue[1] for a video of this.
I suspect more people haven't noticed this because the #1 way to get non-zero vscroll is pixel-scrolling, and pixel-scroll-precision-mode disables the fully-visible cursor line checks which are apparently misbehaving.
>> I've profiled the slow case, see attached for the important parts. As is clear, of the ~8s it took to move to the end of the line (twice), get_next_display_element and set_iterator_to_next are the main culprits (arrived at separately via try_window and partial_line_height) with gui_produce_glyphs contributing.
>
> These are all normally called functions, so the profile doesn't help
> much. My guess is that some of the functions are called an abnormally
> large number of times, but to see that, I need (a) how many times was
> each function called, and (b) across how many characters did Emacs
> move during the time the profile was collected. This is so I could
> calculate how many times each of the functions was called
> _per_character_move_.
I have simplified the test to enable the problematic settings and move just once across the line of 56 chars. This time was very slow; it reports:
Commencing move to end of line with 56 chars [20625]!
Done in (62.586448000000004 18 0.8153190000000023)!
A total of 3383 characters in simple.el were visible during this movement, and one other frame (monitoring *Messages*) was as well. I have expanded all of the relevant profile data, so the sample data are larger; see attached.
The columns are:
# Samples, Self # Samples, Weight (total time), Self Weight (total time in function body)
This (1ms) sampling profile unfortunately doesn't contain call count. I could try to take a look, but you probably have better ideas than me about which functions may be called overly often.
[1] https://github.com/jdtsmith/ultra-scroll/issues/32
[vscroll_lag_profile_simple.txt (text/plain, attachment)]
[test_vscroll_induced_lag_simple.el (application/octet-stream, attachment)]
[Message part 4 (text/plain, inline)]
This bug report was last modified today.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.