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

From: Alan Mackenzie <[email-masked]>
Date: Sat, 11 Dec 2021 17:04:28 +0000

Hello, Eli.

On Sat, Dec 11, 2021 at 17:38:34 +0200, Eli Zaretskii wrote:
> > Date: Sat, 11 Dec 2021 14:52:22 +0000
> > Cc: [email-masked], [email-masked]
> > From: Alan Mackenzie <[email-masked]>

> > OK, I think I see what the problem is, now.  It's the middle line in ....

> >   redisplay_internal 0
> >   071a03c8 (xdisp.c): try_window_id 2
> >   redisplay_preserve_echo_area (8)

> > ..... , which indicates deep processing in redisplay.  (Yes, I know you've
> > been telling me this for a while...)  The question is why does the code
> > get that deep in rather than being aborted earlier?

> I already established that, it's the fact that the buffer's modified
> tick is increasing.  This then causes this test:

>   current_matrix_up_to_date_p
>     = (w->window_end_valid
>        && !current_buffer->clip_changed
>        && !current_buffer->prevent_redisplay_optimizations_p
>        && !window_outdated (w)
>        && !hscrolling_current_line_p (w));

> to fail because window_outdated returns non-zero.  That's how I knew
> that the buffer's modified tick is the culprit.

Ah, OK.  Then this bit seems clear.  With that patch of mine in
textprop.c, which tests inhibit_modification_hooks before modifying the
tick, I don't see the "try_window_id 2" lines in the trace-redisplay
output.

So, I suggest I write a commit message and commit that patch.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Unfortunately, it makes little difference to the CPU usage of CC Mode in
the few minutes after visiting xdisp.c.

> > c-is-sws (along with c-in-sws) marks syntactic whitespace in a buffer so
> > that especially for long comments, passing over that WS is rapid (after
> > the first pass has marked the properties).

> > c-type marks certain types of identifiers and positions related to a CC
> > Mode declaration, e.g. the start of a declarator, or the end of the
> > previous statement.

> > > Could we perhaps refrain from putting them on buffer text when those
> > > functions are called from the timer?

> > That would not be sensible.  Both of them are for optimisation, and
> > preventing them being used from the timer would involve an involved
> > (slow) mechanism.

> But we are talking about the timer whose job is to find type
> declarations.  Does that job require these properties?

I can't say for definite, off hand, but almost certainly yes.  After the
first answer of this post, does it still matter?

> > Another thing.  After waiting the ~2 minutes for the background scanning
> > to complete, I had a look at which character positions had the
> > `fontified' text property, using a simple utility I wrote some years ago:
> > [...]
> > Using the [f10] key (or just typing M-x get-fontified, if F10 is
> > otherwise occupied) the following positions ended up fontified in
> > X-Windows after that 2 minute pause:

> >     "Fontified regions: ((1 . 1740))"

> > ,  That is, at the end, only the visible portion and a bit more were
> > fontified.  This suggests (though not conclusively) that no fontification
> > happened anywhere else in the buffer.

> So why is the timer function keep running for so long, and why does it
> put those two other properties on the rest of the buffer?  It sounds
> to me like you could stop the timer once the visible portion of the
> buffer has been reached, because no type after that can affect
> fontification.

That's sadly not true.  The source code which determines an identifier is
a "found type" is frequently distant from the place where the identifier
needs to be fontified as a type.  For, example, near the beginning of a C
buffer we might have:

    foo (bar, baz);

and somewhere else we have code defining `bar' and `baz' as types, so
that the code line is in fact defining a forward declaration of an int
function, and isn't a function call with two arguments.

Other more usual things (which I can't think of at the moment) caused the
randomness in the fontification which gave rise to that long thread
earlier on in the year.

> You could then restart the timer when the buffer is modified, or if the
> window is scrolled to reveal a portion of the buffer below the current
> end-of-window.

Unfortunately not.  To fontify the current window contents reliably
involves having scanned the entire buffer.

It may well be that this refinement is too expensive in processing power
to be worthwhile.

I am puzzled as to why the mechanism is only taking around 20% - 25% of a
CPU core's time.  It is customised to take (a little more than) 0.05s of
every 0.1s.  Yet it is only taking a third to a half of that amount, even
less when one takes garbage collection into account.

-- 
Alan Mackenzie (Nuremberg, Germany).