Subject: Re: bug#38407: 27.0.50; infinite loop with display of large file without newlines

From: Robert Pluim <[email-masked]>
Date: Thu, 05 Dec 2019 08:27:00 +0100

>>>>> On Wed, 04 Dec 2019 17:45:40 +0200, Eli Zaretskii <[email-masked]> said:
    >> Thread 1 "emacs" hit Breakpoint 3, bidi_shelve_cache () at bidi.c:981
    >> 981	  alloc = (bidi_shelve_header_size
    >> $25 = 30860
    >> $26 = 71842080
    >> 
    >> which means Emacs is copying 70MB of data every time bidi_shelve_cache
    >> is called, and itʼs called *a lot* in this scenario. Could we not do
    >> this shelving by pointer-swapping or similar rather than copying?

    Eli> Not sure I understand what kind of pointer-swapping you had in mind.
    Eli> We don't swap between 2 buffers here, we save away a snapshot of the
    Eli> iterator state each time we see a character where a line break can be
    Eli> made, so that we could restore that state when we exhaust the window's
    Eli> width.  We must restore the iterator state to continue to the next
    Eli> visual line, and the bidi cache is an integral part of that state.

Yes, I hadn't realized you needed to keep a copy of the data.

    Eli> We could perhaps lower the cache size limit (see
    Eli> BIDI_CACHE_MAX_ELTS_PER_SLOT in bidi.c), which would then
    Eli> proportionally decrease the time for making a copy of the
    Eli> cache.

I tried various values of that down to 5000, it improved matters by a
factor of 8 or so, but the resulting Emacs was still pretty laggy
(with visual-line-mode enabled).

    Eli> Or
    Eli> we could make some non-trivial changes in the logic of
    Eli> move_it_in_display_line_to (and similar changes in display_line) to
    Eli> detect when the cache becomes too large, and use a backup algorithm
    Eli> that doesn't copy it.  But I question the utility of such changes:
    Eli> they will never get us a speedup like bidi-inhibit-bpa does, and for
    Eli> the relatively rare use case like this one (extremely long lines in a
    Eli> JSON file, with some bracketed parts containing R2L text, and the user
    Eli> activating visual-line-mode on top of that) inhibiting the BPA,
    Eli> whether via so-long or by the user or some other Lisp, sounds like an
    Eli> okay solution to me.  If the JSON file has long lines, but no R2L
    Eli> text, we already have an optimization in bidi.c to avoid having a
    Eli> large cache; and if visual-line-mode is off, the cache doesn't need to
    Eli> be copied so frequently.  So only the combination of the two causes
    Eli> this tremendous slowdown, and bidi-inhibit-bpa solves it better than
    Eli> any alternative.  WDYT?

That sounds reasonable. I see global-so-long-mode is off by default,
do we want to enable it by default? It seems a dis-service to users to
make them have to find out about it by themselves.

Robert