Subject: bug#56682: Fix the long lines font locking related slowdowns

From: Dmitry Gutov <[email-masked]>
Date: Sat, 13 Aug 2022 20:20:04 +0300

On 13.08.2022 17:24, Gregory Heytings wrote:
> 
>>
>> But they're not. Of course, modes might have problematic rules 
>> (font-lock-keywords are turing-complete, after all), but it might be 
>> just as easy to fix all the main major modes rather than hobble user 
>> experience.
>>
> 
> You've made it quite clear that in your opinion incorrect font locking 
> hobbles user experience more than multi-second delays between motion or 
> search commands.

I did not.

As soon as the file becomes very large, such that font-lock actually 
becomes costly even in properly written major modes, we can still do one 
of the two things: apply narrowing during font-lock, or fontify only the 
beginning of the file.

That's what two alternative values of font-lock-large-files (added on 
the branch) aim to do. But what is the good default value, and if it's 
not t, what thresholds to use, those questions require more testing and 
user feedback.

>> Especially if we limit ourselves to modes that are likely to be used 
>> with large files.
>>
> 
> That's not the intention, no.
> 
>>
>> So please go ahead and experiment, and report on your findings later.
>>
> 
> I already did, and told you that these multi-second delays were still 
> present in larger JSON files (and therefore also in smaller files with 
> slower CPUs).

Delays or "a delay"? Just the first time you scroll to EOB? Or did you 
do the whole dance with editing near BOB, then goto EOB, and repeat?

Did you try that with other file formats? What is the size threshold 
where the performance becomes uncomfortable?

>> Then the goal failed because we don't disable bidi hpa? It has a much 
>> more noticeable effect on editing that font-lock.
>>
> 
> That's not correct, no.  The BPA algorithm makes C-n and C-p slower at 
> the beginning of large files only in a very specific case: when the 
> beginning of the buffer contains opening brackets whose matching closing 
> bracket is at the end of the buffer.

To be fair, that's pretty much all JSON files. But I can't quickly 
recall any other format with that properly, OK.

> And the BPA algorithm does not 
> cause multi-second delays.

The ones I saw seemed pretty bad. And they happened on every command 
invocation, not only after you edit the buffer on some distant position.

And bidi-inhibit-hpa is the main cause of C-v/M-v stuttering over here.

>>> Which is why fixing js-mode, and adding a json-mode, as you did, is a 
>>> "too local" fix. Of course, that doesn't mean what you did is 
>>> useless; it only means that it cannot be considered as a general 
>>> solution to the problem at hand.
>>
>> That's not what the branch contains.
>>
> 
> You're playing with words.  The fixes to js-mode and the added json-mode 
> are not on the branch because you installed them on master, but what you 
> claim the branch demonstrates depends on what you installed on master. 
> Or do you claim that what the branch contains makes editing any other 
> file (that is, not a .js or a .json file) almost as fast as what is on 
> master?

The branch:

1) Allows everyone interested to evaluate the performance of 
unrestricted font-lock even in large files (single-line or not) and see 
how big on a problem the delays caused by syntax-ppss actually are in 
their experience. It's an important question.
2) Figure out the file sizes where syntax-ppss's performance really does 
become a problem. That can give us data for better defaults later.
3) Play around with two easy solutions that we discussed previously: 
narrowing during font-lock (one of the values for font-lock-large-files 
pretty much matches the current behavior on master), or fontifying only 
the first X characters (e.g. 1000000) of the buffer, and skipping on the 
rest.
4) It should be plain to see that implementing additional approaches 
should be easy enough. For instance, a hybrid like "fontify the first 1 
MB correctly, and the rest - on best-effort basis". Although the value 
'(narrow . 1000000) should provide behavior a very similar behavior 
already. Maybe ever a better one: the boundaries are stable. Maybe sure 
to try it together with (setq bidi-inhibit-hpa t): the result looks very 
fast to me.