From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.bugs Subject: bug#69385: 30.0.50; Long lines with bidi text slow down Emacs Date: Sun, 03 Mar 2024 17:18:31 +0200 Message-ID: <86edcrny2g.fsf@gnu.org> References: <878r381pjk.fsf@gmx.net> <86msrowk0g.fsf@gnu.org> <87zfvozaj7.fsf@gmx.net> <86edd0wdbs.fsf@gnu.org> <87r0h0z3fl.fsf@gmx.net> <868r37wgkx.fsf@gnu.org> <87zfvnfh4d.fsf@gmx.net> <86v86bux3w.fsf@gnu.org> <86ttlvuwxo.fsf@gnu.org> <87r0gzfe5a.fsf@gmx.net> <86r0gzusrx.fsf@gnu.org> <87msrnfc7h.fsf@gmx.net> <86o7c3uqqt.fsf@gnu.org> <87il2bf8uz.fsf@gmx.net> <86bk83uj9a.fsf@gnu.org> Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="35852"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 69385@debbugs.gnu.org To: stephen.berman@gmx.net Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Mar 03 16:20:00 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rgnd9-00098a-Pq for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 03 Mar 2024 16:19:59 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rgncl-0000ko-OJ; Sun, 03 Mar 2024 10:19:35 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rgncj-0000kJ-UA for bug-gnu-emacs@gnu.org; Sun, 03 Mar 2024 10:19:34 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rgncj-0003n4-Le for bug-gnu-emacs@gnu.org; Sun, 03 Mar 2024 10:19:33 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rgndC-0000lp-5A for bug-gnu-emacs@gnu.org; Sun, 03 Mar 2024 10:20:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 03 Mar 2024 15:20:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 69385 X-GNU-PR-Package: emacs Original-Received: via spool by 69385-submit@debbugs.gnu.org id=B69385.17094791532894 (code B ref 69385); Sun, 03 Mar 2024 15:20:02 +0000 Original-Received: (at 69385) by debbugs.gnu.org; 3 Mar 2024 15:19:13 +0000 Original-Received: from localhost ([127.0.0.1]:40903 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rgncO-0000kc-Kd for submit@debbugs.gnu.org; Sun, 03 Mar 2024 10:19:13 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:36790) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rgncM-0000kN-0c for 69385@debbugs.gnu.org; Sun, 03 Mar 2024 10:19:11 -0500 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rgnbn-0003iS-DZ; Sun, 03 Mar 2024 10:18:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=Uf6xj6fuko7jXhabk3uQvR9Tv4TsemJK6tbFpfxAbmk=; b=phv241yPcHmS Ne2wxiUA87V12GTKA5KojWys+xjNtL+zqegzpp+ARe8r4kdwWL3sa7a92kVCvq2bje6QNdOmOoEr1 MFnaO+zgTQlu8tT2Ebe/kefIYlASzVQo+1vfzVpohbn3jc1JDfswGQinos2q5oVbQdsW1+9L593bo 6zGDyef8CT8q+3IPPmd8bt+QB/FVVcIVzQZy1JZIqs+YOgrdrZOQuErJlIN1ny6CisCLKF5hqjTnD KOaMuCUgnZhkr76SZPr8nqzWTeS7LBz2HS9ZoFUS83M5INzHWDrdYT3ntLuMXGoSZ4HUz+amtttB7 Nt8jbbLaogO9Ly0gQQB92Q==; In-Reply-To: <86bk83uj9a.fsf@gnu.org> (message from Eli Zaretskii on Mon, 26 Feb 2024 21:18:25 +0200) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:280940 Archived-At: > Cc: 69385@debbugs.gnu.org > Date: Mon, 26 Feb 2024 21:18:25 +0200 > From: Eli Zaretskii > > The reason is that, when a paragraph's direction is right-to-left, > inserting a new glyph into glyph matrices pushes all the previous > glyphs, thus reversing them on the fly. Whereas in LTR paragraphs a > glyph is inserted by adding it to the end of the previous glyphs. And > pushing is more expensive. So now I understand why resetting > bidi-display-reordering had such a dramatic effect in your case: it > makes the paragraph render LTR as its side effect, which avoids the > costly pushing of glyphs. In a very long line, this cost is very > high. > > I will see if we can do better in this matter. Actually, the fact that glyphs are pushed is not the culprit here, since we only push as many glyphs as fit in a screen line, and that cannot be too many. The real culprit is the way we look for the next (actually, previous) composition that includes the given buffer position, when we scan characters backward (due to reordering). The current code causes us to scan all the way to BOB, which is especially painful with long lines without newlines. I've coded an optimization for that, see the patch below. Could you please try running with this patch for a week or two, and see if you can spot any problems? I hope you are editing those files with embedded Arabic frequently enough for these changes to be exercised. If you see no problems after a week or two, I will install this. Thanks. diff --git a/src/bidi.c b/src/bidi.c index 36d1a04..306b44a 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -754,6 +754,16 @@ bidi_cache_find_level_change (int level, int dir, bool before) return -1; } +ptrdiff_t +bidi_level_start (int level) +{ + ptrdiff_t slot = bidi_cache_find_level_change (level, -1, true); + + if (slot >= 0) + return bidi_cache[slot].charpos; + return -1; +} + static void bidi_cache_ensure_space (ptrdiff_t idx) { diff --git a/src/dispextern.h b/src/dispextern.h index 5387cb4..1c3232f 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3438,6 +3438,7 @@ #define TTY_CAP_STRIKE_THROUGH 0x20 extern void *bidi_shelve_cache (void); extern void bidi_unshelve_cache (void *, bool); extern ptrdiff_t bidi_find_first_overridden (struct bidi_it *); +extern ptrdiff_t bidi_level_start (int); /* Defined in xdisp.c */ diff --git a/src/xdisp.c b/src/xdisp.c index d03769e..140d711 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -4353,7 +4353,7 @@ compute_stop_pos (struct it *it) an automatic composition, limit the search of composable characters to that position. */ if (it->bidi_p && it->bidi_it.scan_dir < 0) - stoppos = -1; + stoppos = bidi_level_start (it->bidi_it.resolved_level) - 1; else if (!STRINGP (it->string) && it->cmp_it.stop_pos <= IT_CHARPOS (*it) && cmp_limit_pos > 0) @@ -8712,9 +8712,8 @@ set_iterator_to_next (struct it *it, bool reseat_p) ptrdiff_t stop = it->end_charpos; if (it->bidi_it.scan_dir < 0) - /* Now we are scanning backward and don't know - where to stop. */ - stop = -1; + /* Now we are scanning backward; figure out where to stop. */ + stop = bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop, Qnil, true); } @@ -8745,7 +8744,7 @@ set_iterator_to_next (struct it *it, bool reseat_p) re-compute the stop position for composition. */ ptrdiff_t stop = it->end_charpos; if (it->bidi_it.scan_dir < 0) - stop = -1; + stop = bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop, Qnil, true); @@ -9190,7 +9189,9 @@ get_visually_first_element (struct it *it) bytepos = IT_BYTEPOS (*it); } if (it->bidi_it.scan_dir < 0) - stop = -1; + stop = STRINGP (it->string) + ? -1 + : bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop, it->string, true); } @@ -9694,9 +9695,10 @@ next_element_from_buffer (struct it *it) && PT < it->end_charpos) ? PT : it->end_charpos; } else - stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos; - if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it), - stop) + stop = it->bidi_it.scan_dir < 0 + ? bidi_level_start (it->bidi_it.resolved_level) - 1 + : it->end_charpos; + if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop) && next_element_from_composition (it)) { return true;