Subject: bug#52298: 29.0.50; Frequent redisplay cycles induced by c-type-finder-timer-func timer in CC Mode

From: Eli Zaretskii <[email-masked]>
Date: Thu, 09 Dec 2021 09:08:16 +0200

> Date: Wed, 8 Dec 2021 20:15:46 +0000
> Cc: [email-masked]
> From: Alan Mackenzie <[email-masked]>
> 
> I've just tried building with that ./configure option, and trying out
> M-x trace-redisplay with emacs -Q on a very recent master version.
> 
> The command is not very useful on a Linux console.

I didn't suggest that you invoke that command, it is not part of this
issue.  It is just a tool I used to see what's going on, and I do know
how to interpret its output.

And yes, if your main development environment is based on the Linux
console, then many tools will be unavailable to you, but that's a
tangent.

> It outputs messages
> on the same display thing that Emacs itself is using, and outputs them
> as if they were a Unix text file being naively displayed in Windows:
> i.e. like this:
> 
> aaaa
>     aaaaaaaaaaaaa
>                  aaaaaaaaaaaaa
> 		              aaaaaaaaaaaaaaa
> 			                     aaaaaaaaaaaaaaaaaa

That's not related to Windows, that's because Emacs switches the
terminal to a mode where newline doesn't cause the cursor to move to
the beginning of the next line.  IOW, this is because you are running
Emacs on the Linux console and the traces go to the same console,
which is not configured to receive simple printf's.

> >   redisplay_internal 0
> >   071a03c8 (xdisp.c): try_window_id 2
> >   redisplay_preserve_echo_area (8)
> 
> > means that the processing induced by that timer function is far from
> > being trivial, which means something that this function does causes
> > Emacs to think some real change might have happened in the buffer.
> 
> I'm not familiar with such traces, and trace-redisplay is not documented
> in its doc string.  Could you please explain briefly  what the "071a03c8
> (xdisp.c):" means, and what says that the processing is non-trivial.

The address and the file name are for when you run under GDB.  The
important part of that message is "try_window_id 2".  If you look in
xdisp.c for the trace that emits it, viz.:

      debug_method_add (w, "try_window_id %d", tem);

you will realize that redisplay called try_window_id, which means it
was working too hard: since nothing has changed in the buffer, and
even point didn't move, it should have succeeded in the call to
try_cursor_movement, which is before it.  So something prevented
try_cursor_movement from succeeding in this case, and kept preventing
that for full 4 minutes after the file was visited.  The question is:
what is that something that causes try_cursor_movement to fail?

> > Is it possible to prevent this frequent timer from firing when no
> > changes have been done to the buffer?  And in any case, please try to
> > include some logic in that function to avoid whatever it does now to
> > force such frequent non-trivial redisplay cycles.  If nothing else,
> > laptop users will hate us if we release Emacs with this behavior.
> 
> When I apply the following patch to cc-fonts.el:
> 
> diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
> index 967464ac14..2ae92f99bf 100644
> --- a/lisp/progmodes/cc-fonts.el
> +++ b/lisp/progmodes/cc-fonts.el
> @@ -2429,6 +2429,11 @@ c-re-redisplay-timer
>  (defun c-force-redisplay (start end)
>    ;; Force redisplay immediately.  This assumes `font-lock-support-mode' is
>    ;; 'jit-lock-mode.  Set the variable `c-re-redisplay-timer' to nil.
> +;;;; TEMPORARY STOUGH, 2021-12-08
> +  (message "c-force-redisplay - Buffer: %s - %s:%s - \"%s\""
> +          (buffer-name (current-buffer)) start end
> +          (buffer-substring-no-properties start end))
> +;;;; END OF TEMPORARY STOUGH.
>    (save-excursion (c-font-lock-fontify-region start end))
>    (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
>    (setq c-re-redisplay-timer nil))
> 
> , and load xdisp.c freshly, I see only three lines of output in
> *Messages*:
> 
> c-force-redisplay - Buffer: xdisp.c - 223:225 - "it"
> c-force-redisplay - Buffer: xdisp.c - 49:55 - "buffer"
> c-force-redisplay - Buffer: xdisp.c - 28:34 - "window"
> 
> That applies after waiting over a minute.  After this time, the `top'
> utility shows Emacs consuming around 1% of a CPU core's time.
> 
> All this suggests that in normal use, CC Mode isn't triggering excessive
> redisplay operations.

No, it means that your hypothesis regarding what causes the phenomenon
was incorrect.  Something else prevents try_cursor_movement from
successfully deciding that the window doesn't need any redisplay.
That something is in the timer function the CC Mode runs.  If you can
find what that factor is and remove it, it will solve the issue.

In a followup message I wrote:

> Is your code using with-silent-modifications, or some other mechanism
> that should prevent Emacs from thinking that the buffer has changed?
> If not, why not?

Can you please answer that?  It might be the key to unlock this issue,
since you said that timer function puts text properties on buffer
text.

Thanks.