From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs Subject: bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag Date: Fri, 29 Nov 2024 23:18:02 +0000 Message-ID: References: <86v7wphrmi.fsf@gnu.org> <86ed3cinfg.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="15407"; mail-complaints-to="usenet@ciao.gmane.io" Cc: acm@muc.de, Eli Zaretskii , 74357@debbugs.gnu.org To: =?UTF-8?Q?Bj=C3=B6rn?= Lindqvist Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Nov 30 00:19:21 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 1tHAGe-0003qq-EK for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 30 Nov 2024 00:19:20 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tHAGO-0002K3-7M; Fri, 29 Nov 2024 18:19:04 -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 1tHAGM-0002Jq-5P for bug-gnu-emacs@gnu.org; Fri, 29 Nov 2024 18:19:02 -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 1tHAGL-0000Ii-St for bug-gnu-emacs@gnu.org; Fri, 29 Nov 2024 18:19:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=From:In-Reply-To:MIME-Version:References:Date:To:Subject; bh=54VZ1oCmb53jlq2NN7qgTSHzIyKoY/Blmi/zLwhOP0s=; b=j4YpAD2uM9G76NUUnvejcjaiQNYLj8fpjrNvpzN/MOAuakbwPfuXyFgZRktu0R4OuaK7SrUJUoX2SemuCCxYcZojGP5OpU2PQtPcuhV4lynunv6nvaXJ4etDbVx0TWURj/LoBOpGZ/SVHpoQ4Wp/9dBHKwXuXpPhZBUaAcuUWx1tKJWbyI+FV9Thldkma8K04ZLk1/nAa6AlrK42UFP8QzwnTIDwMB1Fylpua69HEkBE/c97twDuJhBHp9fPL4mwrOll5udcfGSnx5hwRng6e+kXYBgFoZBGQLqhd3883PdDyjgOei19CbGFGMAUhKSduAJJsodutMTbAJpIn1+NWw==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1tHAGL-0007Fi-NH for bug-gnu-emacs@gnu.org; Fri, 29 Nov 2024 18:19:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Alan Mackenzie Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 29 Nov 2024 23:19:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 74357 X-GNU-PR-Package: emacs Original-Received: via spool by 74357-submit@debbugs.gnu.org id=B74357.173292229227798 (code B ref 74357); Fri, 29 Nov 2024 23:19:01 +0000 Original-Received: (at 74357) by debbugs.gnu.org; 29 Nov 2024 23:18:12 +0000 Original-Received: from localhost ([127.0.0.1]:44755 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tHAFY-0007EI-6O for submit@debbugs.gnu.org; Fri, 29 Nov 2024 18:18:12 -0500 Original-Received: from mail.muc.de ([193.149.48.3]:20172) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tHAFW-0007E1-65 for 74357@debbugs.gnu.org; Fri, 29 Nov 2024 18:18:11 -0500 Original-Received: (qmail 11643 invoked by uid 3782); 30 Nov 2024 00:18:03 +0100 Original-Received: from muc.de (p4fe15997.dip0.t-ipconnect.de [79.225.89.151]) (using STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP; Sat, 30 Nov 2024 00:18:02 +0100 Original-Received: (qmail 31109 invoked by uid 1000); 29 Nov 2024 23:18:02 -0000 Content-Disposition: inline In-Reply-To: X-Submission-Agent: TMDA/1.3.x (Ph3nix) X-Primary-Address: acm@muc.de 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:296105 Archived-At: Hello again, Björn. On Thu, Nov 28, 2024 at 20:03:33 +0000, Alan Mackenzie wrote: > On Fri, Nov 15, 2024 at 22:43:45 +0100, Björn Lindqvist wrote: > > Den fre 15 nov. 2024 kl 15:25 skrev Eli Zaretskii : > > > Can you tell where in real life do you see such deeply-nested braces > > > in C source files? > > 50 is perhaps exaggerating it, but in "modern" C++ with multiple > > namespaces, nested classes, and anonymous functions you can easily get > > scopes nested over a dozen levels deep. > In your test file, near the end, holding down the 'y' key as you > describe, most of the time CC Mode is scanning for brace lists (and not > finding them). ("Brace lists" are things like the initialisation forms > for structs and arrays, not statement blocks.) > There is a cache mechanism to help reduce this scanning, but with the > deep nesting in the test file, it seems to be ineffective, with elements > of that cache continually being overwritten by new elements. The cache > currently has just four elements. Maybe it would be better to increase > that number. Maybe there's some other problem with the cache. I'm > looking into it. It turns out that that cache mechanism was almost totally ineffective. I've put a new cache into c-inside-bracelist-p. More precisely, I've reused an existing cache in a new way. Would you please apply the patch below to your CC Mode, byte compile CC Mode, and test it a bit to see if it's fast enough. (If you want any help applying the patch or byte compiling the result, feel free to send me private email.) Thanks! diff -r 2c1ba136f3f2 cc-engine.el --- a/cc-engine.el Mon Oct 28 15:47:50 2024 +0000 +++ b/cc-engine.el Fri Nov 29 23:12:27 2024 +0000 @@ -13178,7 +13178,7 @@ (setq c-laomib-cache (delq elt c-laomib-cache))))))) (defun c-looking-at-or-maybe-in-bracelist (&optional containing-sexp lim) - ;; Point is at an open brace. If this starts a brace list, return a list + ;; Point is at an open brace. If this starts a brace list, return a cons ;; whose car is the buffer position of the start of the construct which ;; introduces the list, and whose cdr is the symbol `in-paren' if the brace ;; is directly enclosed in a parenthesis form (i.e. an arglist), t if we @@ -13411,14 +13411,19 @@ (t t)))) ;; The caller can go up one level. )))) +;; A list of the form returned by `c-parse-state'. Each opening brace in it +;; is not the brace of a brace list. +(defvar c-no-bracelist-cache nil) +(make-variable-buffer-local 'c-no-bracelist-cache) + (defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren) - ;; return the buffer position of the beginning of the brace list statement + ;; Return the buffer position of the beginning of the brace list statement ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil. ;; - ;; CONTAINING-SEXP is the buffer pos of the innermost containing paren. NO - ;; IT ISN'T!!! [This function is badly designed, and probably needs - ;; reformulating without its first argument, and the critical position being - ;; at point.] + ;; CONTAINING-SEXP must be at an open brace, and is the buffer pos of the + ;; innermost containing brace. NO IT ISN'T!!! [This function is badly + ;; designed, and probably needs reformulating without its first argument, + ;; and the critical position being at point.] ;; ;; PAREN-STATE is the remainder of the state of enclosing braces. ;; ACCEPT-IN-PAREN is non-nil iff we will accept as a brace list a brace @@ -13432,32 +13437,42 @@ ;; speed. ;; ;; This function might do hidden buffer changes. - ;; this will pick up array/aggregate init lists, even if they are nested. - (save-excursion - (let ((bufpos t) - next-containing) - (while (and (eq bufpos t) - containing-sexp) - (when paren-state - (setq next-containing (c-pull-open-brace paren-state))) - - (goto-char containing-sexp) - (if (c-looking-at-inexpr-block next-containing next-containing) - ;; We're in an in-expression block of some kind. Do not - ;; check nesting. We deliberately set the limit to the - ;; containing sexp, so that c-looking-at-inexpr-block - ;; doesn't check for an identifier before it. - (setq bufpos nil) - (if (not (eq (char-after) ?{)) - (setq bufpos nil) - (when (eq (setq bufpos (c-looking-at-or-maybe-in-bracelist - next-containing next-containing)) - t) - (setq containing-sexp next-containing - next-containing nil))))) - (and (consp bufpos) - (or accept-in-paren (not (eq (cdr bufpos) 'in-paren))) - (car bufpos))))) + ;; It will pick up array/aggregate init lists, even if they are nested. + (save-excursion + (let ((bufpos t) + next-containing + (whole-paren-state (cons containing-sexp paren-state)) + (current-brace containing-sexp)) + (while (and (eq bufpos t) + current-brace + (not (memq current-brace c-no-bracelist-cache))) + (when paren-state + (setq next-containing (c-pull-open-brace paren-state))) + + (goto-char current-brace) + (cond + ((c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq bufpos nil)) + ((not (eq (char-after) ?{)) + (setq bufpos nil)) + ((eq (setq bufpos (c-looking-at-or-maybe-in-bracelist + next-containing next-containing)) + t) + (setq current-brace + next-containing + next-containing nil)))) + (cond + ((and (consp bufpos) + (or accept-in-paren (not (eq (cdr bufpos) 'in-paren)))) + (car bufpos)) + ((not (memq containing-sexp c-no-bracelist-cache)) + ;; Update `c-no-bracelist-cache' + (setq c-no-bracelist-cache (copy-tree whole-paren-state)) + nil))))) (defun c-looking-at-special-brace-list () ;; If we're looking at the start of a pike-style list, i.e., `({ })', diff -r 2c1ba136f3f2 cc-mode.el --- a/cc-mode.el Mon Oct 28 15:47:50 2024 +0000 +++ b/cc-mode.el Fri Nov 29 23:12:27 2024 +0000 @@ -2313,7 +2313,9 @@ ;; The following must happen after the previous, which likely alters ;; the macro cache. (when c-opt-cpp-symbol - (c-invalidate-macro-cache beg end))))) + (c-invalidate-macro-cache beg end)) + (setq c-no-bracelist-cache + (c-whack-state-after beg c-no-bracelist-cache))))) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) > > -- > > mvh/best regards Björn Lindqvist -- Alan Mackenzie (Nuremberg, Germany).