GNU bug report logs - #35316
26.2; Emacs lags in c++-mode buffer when editing with iedit-mode on

Previous Next

Packages: emacs, cc-mode;

Reported by: Zhang Haijun <ccsmile2008 <at> outlook.com>

Date: Fri, 19 Apr 2019 00:24:01 UTC

Severity: normal

Tags: fixed

Found in version 26.2

Fixed in version 28.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 35316 in the body.
You can then email your comments to 35316 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#35316; Package emacs. (Fri, 19 Apr 2019 00:24:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Zhang Haijun <ccsmile2008 <at> outlook.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 19 Apr 2019 00:24:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: "bug-gnu-emacs <at> gnu.org" <bug-gnu-emacs <at> gnu.org>
Subject: 26.2; Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Fri, 19 Apr 2019 00:22:59 +0000
iedit.el(https://github.com/victorhge/iedit) is a multiple-cursors like package. It can setup more than one virtual cursors at different positions in the buffer. When you edit in the buffer, it clones changes at the main cursor to all other virtual cursors.

The problem is that: Emacs lags too much when editing in c++-mode with iedit-mode on.
Profiler shows that cpu are most used by c-after-change.

The related issue: https://github.com/victorhge/iedit/issues/83



In GNU Emacs 26.2 (build 1, x86_64-apple-darwin17.7.0, NS appkit-1561.60 Version 10.13.6 (Build 17G6030))
 of 2019-04-13 built on jundeMac
Windowing system distributor 'Apple', version 10.3.1561
Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.

Configured using:
 'configure --with-ns '--enable-locallisppath=/Library/Application
 Support/Emacs/${version}/site-lisp:/Library/Application
 Support/Emacs/site-lisp' --with-modules --disable-acl
 --without-makeinfo 'CC=cc ' CFLAGS=-O2
 PKG_CONFIG_PATH=/Users/jun/source/build-emacs-master/brew/lib/pkgconfig:'

Configured features:
JPEG NOTIFY GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS MODULES THREADS
LCMS2

Important settings:
  value of $LANG: zh_CN.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message rmc puny seq byte-opt gv
bytecomp byte-compile cconv cl-loaddefs cl-lib dired dired-loaddefs
format-spec rfc822 mml easymenu mml-sec password-cache epa derived epg
epg-config gnus-util rmail rmail-loaddefs mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils elec-pair time-date
china-util tooltip eldoc electric uniquify ediff-hook vc-hooks
lisp-float-type mwheel term/ns-win ns-win ucs-normalize mule-util
term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page menu-bar rfn-eshadow isearch timer select
scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite charscript charprop case-table epa-hook jka-cmpr-hook
help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs
button faces cus-face macroexp files text-properties overlay sha1 md5
base64 format env code-pages mule custom widget hashtable-print-readable
backquote threads kqueue cocoa ns lcms2 multi-tty make-network-process
emacs)

Memory information:
((conses 16 205104 12763)
 (symbols 48 20136 0)
 (miscs 40 373 202)
 (strings 32 28953 1768)
 (string-bytes 1 764912)
 (vectors 16 35914)
 (vector-slots 8 784151 7972)
 (floats 8 48 311)
 (intervals 56 224 0)
 (buffers 992 11))


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#35316; Package emacs. (Fri, 19 Apr 2019 00:33:02 GMT) Full text and rfc822 format available.

Message #8 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: 26.2; Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Fri, 19 Apr 2019 00:32:34 +0000
[Message part 1 (text/plain, inline)]
Reproducing steps:
1. emacs -Q
2. Eval code: (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/“))
3. install the package iedit (version from melpa)
4. open the attachment c++ file, and goto line 262 and column 17. cursor will be on word “subsession"
5. M-x narrow-to-defun
6. M-x iedit-mode
7. M-x widen
8. You will see the lag when inputting chars.




[Message part 2 (text/html, inline)]
[QuickTimeFileSink.cpp (application/octet-stream, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#35316; Package emacs. (Fri, 19 Apr 2019 16:21:01 GMT) Full text and rfc822 format available.

Message #11 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Zhang Haijun <ccsmile2008 <at> outlook.com>
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2;
 Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Fri, 19 Apr 2019 12:20:14 -0400
> Reproducing steps:
> 1. emacs -Q
> 2. Eval code: (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/“))
> 3. install the package iedit (version from melpa)
> 4. open the attachment c++ file, and goto line 262 and column 17. cursor
> will be on word “subsession"
> 5. M-x narrow-to-defun
> 6. M-x iedit-mode
> 7. M-x widen
> 8. You will see the lag when inputting chars.

This seems to be a good use case for my syntax-propertize patch.
I just tried it on your test case and while there is still a slight slow
down, it seemed to be much less problematic.

BEWARE: it likely introduces bugs.


        Stefan


diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 49268c4482..31f5ecdfdb 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -506,6 +506,8 @@ c-just-done-before-change
 ;; and `after-change-functions'.  Note that this variable is not set when
 ;; `c-before-change' is invoked by a change to text properties.
 
+(defvar c--use-syntax-propertize t)
+
 (defun c-basic-common-init (mode default-style)
   "Do the necessary initialization for the syntax handling routines
 and the line breaking/filling code.  Intended to be used by other
@@ -648,12 +650,17 @@ c-basic-common-init
 
   ;; Install the functions that ensure that various internal caches
   ;; don't become invalid due to buffer changes.
-  (when (featurep 'xemacs)
-    (make-local-hook 'before-change-functions)
-    (make-local-hook 'after-change-functions))
-  (add-hook 'before-change-functions 'c-before-change nil t)
-  (setq c-just-done-before-change nil)
-  (add-hook 'after-change-functions 'c-after-change nil t)
+  (if c--use-syntax-propertize
+      (setq-local syntax-propertize-function
+		  (lambda (start end)
+		    (c-before-change start (point-max))
+		    (c-after-change start end (- end start))))
+    (when (featurep 'xemacs)
+      (make-local-hook 'before-change-functions)
+      (make-local-hook 'after-change-functions))
+    (add-hook 'before-change-functions 'c-before-change nil t)
+    (setq c-just-done-before-change nil)
+    (add-hook 'after-change-functions 'c-after-change nil t))
   (when (boundp 'font-lock-extend-after-change-region-function)
     (set (make-local-variable 'font-lock-extend-after-change-region-function)
          'c-extend-after-change-region))) ; Currently (2009-05) used by all
@@ -711,15 +718,17 @@ c-common-init
     (widen)
     (setq c-new-BEG (point-min))
     (setq c-new-END (point-max))
-    (save-excursion
-      (let (before-change-functions after-change-functions)
-	(mapc (lambda (fn)
-		(funcall fn (point-min) (point-max)))
-	      c-get-state-before-change-functions)
-	(mapc (lambda (fn)
-		(funcall fn (point-min) (point-max)
-			 (- (point-max) (point-min))))
-	      c-before-font-lock-functions))))
+    (unless c--use-syntax-propertize
+      (save-excursion
+	(let (before-change-functions after-change-functions)
+	  (mapc (lambda (fn)
+		  (funcall fn (point-min) (point-max)))
+		c-get-state-before-change-functions)
+	  (mapc (lambda (fn)
+		  (funcall fn (point-min) (point-max)
+			   (- (point-max) (point-min))))
+		c-before-font-lock-functions)
+	  ))))
 
   (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
   (set (make-local-variable 'outline-level) 'c-outline-level)
@@ -1954,6 +1963,12 @@ c-font-lock-fontify-region
   ;;
   ;; Type a space in the first blank line, and the fontification of the next
   ;; line was fouled up by context fontification.
+  (when c--use-syntax-propertize
+    ;; This should also update c-new-END and c-new-BEG.
+    (syntax-propertize end)
+    ;; FIXME: Apparently `c-new-END' may be left unchanged to a stale value,
+    ;; presumably when the buffer gets truncated.
+    (if (> c-new-END (point-max)) (setq c-new-END (point-max))))
   (let (new-beg new-end new-region case-fold-search)
     (if (and c-in-after-change-fontification
 	     (< beg c-new-END) (> end c-new-BEG))
@@ -1992,7 +2007,8 @@ c-font-lock-fontify-region
 (defun c-after-font-lock-init ()
   ;; Put on `font-lock-mode-hook'.  This function ensures our after-change
   ;; function will get executed before the font-lock one.
-  (when (memq #'c-after-change after-change-functions)
+  (when (and c--use-syntax-propertize
+	     (memq #'c-after-change after-change-functions))
     (remove-hook 'after-change-functions #'c-after-change t)
     (add-hook 'after-change-functions #'c-after-change nil t)))
 
@@ -2046,11 +2062,14 @@ c-extend-after-change-region
   (when (eq font-lock-support-mode 'jit-lock-mode)
     (save-restriction
       (widen)
+      ;; FIXME: This presumes that c-new-BEG and c-new-END have been set
+      ;; I guess from the before-change-function.
       (c-save-buffer-state () ; Protect the undo-list from put-text-property.
 	(if (< c-new-BEG beg)
 	    (put-text-property c-new-BEG beg 'fontified nil))
 	(if (> c-new-END end)
-	    (put-text-property end c-new-END 'fontified nil)))))
+	    (put-text-property end (min c-new-END (point-max))
+			       'fontified nil)))))
   (cons c-new-BEG c-new-END))
 
 ;; Emacs < 22 and XEmacs




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#35316; Package emacs. (Sat, 20 Apr 2019 02:46:01 GMT) Full text and rfc822 format available.

Message #14 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Sat, 20 Apr 2019 02:44:57 +0000
I will try it for some days and give feedback.

> 在 2019年4月20日,上午12:20,Stefan Monnier <monnier <at> IRO.UMontreal.CA> 写道:
> 
>> Reproducing steps:
>> 1. emacs -Q
>> 2. Eval code: (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/“))
>> 3. install the package iedit (version from melpa)
>> 4. open the attachment c++ file, and goto line 262 and column 17. cursor
>> will be on word “subsession"
>> 5. M-x narrow-to-defun
>> 6. M-x iedit-mode
>> 7. M-x widen
>> 8. You will see the lag when inputting chars.
> 
> This seems to be a good use case for my syntax-propertize patch.
> I just tried it on your test case and while there is still a slight slow
> down, it seemed to be much less problematic.
> 
> BEWARE: it likely introduces bugs.
> 
> 
>        Stefan
> 
> 
> diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
> index 49268c4482..31f5ecdfdb 100644
> --- a/lisp/progmodes/cc-mode.el
> +++ b/lisp/progmodes/cc-mode.el
> @@ -506,6 +506,8 @@ c-just-done-before-change
> ;; and `after-change-functions'.  Note that this variable is not set when
> ;; `c-before-change' is invoked by a change to text properties.
> 
> +(defvar c--use-syntax-propertize t)
> +
> (defun c-basic-common-init (mode default-style)
>   "Do the necessary initialization for the syntax handling routines
> and the line breaking/filling code.  Intended to be used by other
> @@ -648,12 +650,17 @@ c-basic-common-init
> 
>   ;; Install the functions that ensure that various internal caches
>   ;; don't become invalid due to buffer changes.
> -  (when (featurep 'xemacs)
> -    (make-local-hook 'before-change-functions)
> -    (make-local-hook 'after-change-functions))
> -  (add-hook 'before-change-functions 'c-before-change nil t)
> -  (setq c-just-done-before-change nil)
> -  (add-hook 'after-change-functions 'c-after-change nil t)
> +  (if c--use-syntax-propertize
> +      (setq-local syntax-propertize-function
> +		  (lambda (start end)
> +		    (c-before-change start (point-max))
> +		    (c-after-change start end (- end start))))
> +    (when (featurep 'xemacs)
> +      (make-local-hook 'before-change-functions)
> +      (make-local-hook 'after-change-functions))
> +    (add-hook 'before-change-functions 'c-before-change nil t)
> +    (setq c-just-done-before-change nil)
> +    (add-hook 'after-change-functions 'c-after-change nil t))
>   (when (boundp 'font-lock-extend-after-change-region-function)
>     (set (make-local-variable 'font-lock-extend-after-change-region-function)
>          'c-extend-after-change-region))) ; Currently (2009-05) used by all
> @@ -711,15 +718,17 @@ c-common-init
>     (widen)
>     (setq c-new-BEG (point-min))
>     (setq c-new-END (point-max))
> -    (save-excursion
> -      (let (before-change-functions after-change-functions)
> -	(mapc (lambda (fn)
> -		(funcall fn (point-min) (point-max)))
> -	      c-get-state-before-change-functions)
> -	(mapc (lambda (fn)
> -		(funcall fn (point-min) (point-max)
> -			 (- (point-max) (point-min))))
> -	      c-before-font-lock-functions))))
> +    (unless c--use-syntax-propertize
> +      (save-excursion
> +	(let (before-change-functions after-change-functions)
> +	  (mapc (lambda (fn)
> +		  (funcall fn (point-min) (point-max)))
> +		c-get-state-before-change-functions)
> +	  (mapc (lambda (fn)
> +		  (funcall fn (point-min) (point-max)
> +			   (- (point-max) (point-min))))
> +		c-before-font-lock-functions)
> +	  ))))
> 
>   (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
>   (set (make-local-variable 'outline-level) 'c-outline-level)
> @@ -1954,6 +1963,12 @@ c-font-lock-fontify-region
>   ;;
>   ;; Type a space in the first blank line, and the fontification of the next
>   ;; line was fouled up by context fontification.
> +  (when c--use-syntax-propertize
> +    ;; This should also update c-new-END and c-new-BEG.
> +    (syntax-propertize end)
> +    ;; FIXME: Apparently `c-new-END' may be left unchanged to a stale value,
> +    ;; presumably when the buffer gets truncated.
> +    (if (> c-new-END (point-max)) (setq c-new-END (point-max))))
>   (let (new-beg new-end new-region case-fold-search)
>     (if (and c-in-after-change-fontification
> 	     (< beg c-new-END) (> end c-new-BEG))
> @@ -1992,7 +2007,8 @@ c-font-lock-fontify-region
> (defun c-after-font-lock-init ()
>   ;; Put on `font-lock-mode-hook'.  This function ensures our after-change
>   ;; function will get executed before the font-lock one.
> -  (when (memq #'c-after-change after-change-functions)
> +  (when (and c--use-syntax-propertize
> +	     (memq #'c-after-change after-change-functions))
>     (remove-hook 'after-change-functions #'c-after-change t)
>     (add-hook 'after-change-functions #'c-after-change nil t)))
> 
> @@ -2046,11 +2062,14 @@ c-extend-after-change-region
>   (when (eq font-lock-support-mode 'jit-lock-mode)
>     (save-restriction
>       (widen)
> +      ;; FIXME: This presumes that c-new-BEG and c-new-END have been set
> +      ;; I guess from the before-change-function.
>       (c-save-buffer-state () ; Protect the undo-list from put-text-property.
> 	(if (< c-new-BEG beg)
> 	    (put-text-property c-new-BEG beg 'fontified nil))
> 	(if (> c-new-END end)
> -	    (put-text-property end c-new-END 'fontified nil)))))
> +	    (put-text-property end (min c-new-END (point-max))
> +			       'fontified nil)))))
>   (cons c-new-BEG c-new-END))
> 
> ;; Emacs < 22 and XEmacs


Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Thu, 09 May 2019 13:24:02 GMT) Full text and rfc822 format available.

Message #17 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Thu, 9 May 2019 13:23:42 +0000
I find that I had too little time editing c/c++ source files recently. Because our project switched to golang.

So I didn’t test this patch too much. I just applied the patch and tested iedit with some c++ files and the lag disappeared.


> 在 2019年4月20日,上午10:44,张海君 <ccsmile2008 <at> outlook.com> 写道:
> 
> I will try it for some days and give feedback.
> 
>> 在 2019年4月20日,上午12:20,Stefan Monnier <monnier <at> IRO.UMontreal.CA> 写道:
>> 
>>> Reproducing steps:
>>> 1. emacs -Q
>>> 2. Eval code: (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/“))
>>> 3. install the package iedit (version from melpa)
>>> 4. open the attachment c++ file, and goto line 262 and column 17. cursor
>>> will be on word “subsession"
>>> 5. M-x narrow-to-defun
>>> 6. M-x iedit-mode
>>> 7. M-x widen
>>> 8. You will see the lag when inputting chars.
>> 
>> This seems to be a good use case for my syntax-propertize patch.
>> I just tried it on your test case and while there is still a slight slow
>> down, it seemed to be much less problematic.
>> 
>> BEWARE: it likely introduces bugs.
>> 
>> 
>>       Stefan
>> 
>> 
>> diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
>> index 49268c4482..31f5ecdfdb 100644
>> --- a/lisp/progmodes/cc-mode.el
>> +++ b/lisp/progmodes/cc-mode.el
>> @@ -506,6 +506,8 @@ c-just-done-before-change
>> ;; and `after-change-functions'.  Note that this variable is not set when
>> ;; `c-before-change' is invoked by a change to text properties.
>> 
>> +(defvar c--use-syntax-propertize t)
>> +
>> (defun c-basic-common-init (mode default-style)
>>  "Do the necessary initialization for the syntax handling routines
>> and the line breaking/filling code.  Intended to be used by other
>> @@ -648,12 +650,17 @@ c-basic-common-init
>> 
>>  ;; Install the functions that ensure that various internal caches
>>  ;; don't become invalid due to buffer changes.
>> -  (when (featurep 'xemacs)
>> -    (make-local-hook 'before-change-functions)
>> -    (make-local-hook 'after-change-functions))
>> -  (add-hook 'before-change-functions 'c-before-change nil t)
>> -  (setq c-just-done-before-change nil)
>> -  (add-hook 'after-change-functions 'c-after-change nil t)
>> +  (if c--use-syntax-propertize
>> +      (setq-local syntax-propertize-function
>> +		  (lambda (start end)
>> +		    (c-before-change start (point-max))
>> +		    (c-after-change start end (- end start))))
>> +    (when (featurep 'xemacs)
>> +      (make-local-hook 'before-change-functions)
>> +      (make-local-hook 'after-change-functions))
>> +    (add-hook 'before-change-functions 'c-before-change nil t)
>> +    (setq c-just-done-before-change nil)
>> +    (add-hook 'after-change-functions 'c-after-change nil t))
>>  (when (boundp 'font-lock-extend-after-change-region-function)
>>    (set (make-local-variable 'font-lock-extend-after-change-region-function)
>>         'c-extend-after-change-region))) ; Currently (2009-05) used by all
>> @@ -711,15 +718,17 @@ c-common-init
>>    (widen)
>>    (setq c-new-BEG (point-min))
>>    (setq c-new-END (point-max))
>> -    (save-excursion
>> -      (let (before-change-functions after-change-functions)
>> -	(mapc (lambda (fn)
>> -		(funcall fn (point-min) (point-max)))
>> -	      c-get-state-before-change-functions)
>> -	(mapc (lambda (fn)
>> -		(funcall fn (point-min) (point-max)
>> -			 (- (point-max) (point-min))))
>> -	      c-before-font-lock-functions))))
>> +    (unless c--use-syntax-propertize
>> +      (save-excursion
>> +	(let (before-change-functions after-change-functions)
>> +	  (mapc (lambda (fn)
>> +		  (funcall fn (point-min) (point-max)))
>> +		c-get-state-before-change-functions)
>> +	  (mapc (lambda (fn)
>> +		  (funcall fn (point-min) (point-max)
>> +			   (- (point-max) (point-min))))
>> +		c-before-font-lock-functions)
>> +	  ))))
>> 
>>  (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
>>  (set (make-local-variable 'outline-level) 'c-outline-level)
>> @@ -1954,6 +1963,12 @@ c-font-lock-fontify-region
>>  ;;
>>  ;; Type a space in the first blank line, and the fontification of the next
>>  ;; line was fouled up by context fontification.
>> +  (when c--use-syntax-propertize
>> +    ;; This should also update c-new-END and c-new-BEG.
>> +    (syntax-propertize end)
>> +    ;; FIXME: Apparently `c-new-END' may be left unchanged to a stale value,
>> +    ;; presumably when the buffer gets truncated.
>> +    (if (> c-new-END (point-max)) (setq c-new-END (point-max))))
>>  (let (new-beg new-end new-region case-fold-search)
>>    (if (and c-in-after-change-fontification
>> 	     (< beg c-new-END) (> end c-new-BEG))
>> @@ -1992,7 +2007,8 @@ c-font-lock-fontify-region
>> (defun c-after-font-lock-init ()
>>  ;; Put on `font-lock-mode-hook'.  This function ensures our after-change
>>  ;; function will get executed before the font-lock one.
>> -  (when (memq #'c-after-change after-change-functions)
>> +  (when (and c--use-syntax-propertize
>> +	     (memq #'c-after-change after-change-functions))
>>    (remove-hook 'after-change-functions #'c-after-change t)
>>    (add-hook 'after-change-functions #'c-after-change nil t)))
>> 
>> @@ -2046,11 +2062,14 @@ c-extend-after-change-region
>>  (when (eq font-lock-support-mode 'jit-lock-mode)
>>    (save-restriction
>>      (widen)
>> +      ;; FIXME: This presumes that c-new-BEG and c-new-END have been set
>> +      ;; I guess from the before-change-function.
>>      (c-save-buffer-state () ; Protect the undo-list from put-text-property.
>> 	(if (< c-new-BEG beg)
>> 	    (put-text-property c-new-BEG beg 'fontified nil))
>> 	(if (> c-new-END end)
>> -	    (put-text-property end c-new-END 'fontified nil)))))
>> +	    (put-text-property end (min c-new-END (point-max))
>> +			       'fontified nil)))))
>>  (cons c-new-BEG c-new-END))
>> 
>> ;; Emacs < 22 and XEmacs
> 


Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Thu, 16 May 2019 15:06:02 GMT) Full text and rfc822 format available.

Message #20 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Zhang Haijun <ccsmile2008 <at> outlook.com>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 35316 <at> debbugs.gnu.org
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Thu, 16 May 2019 15:04:57 +0000
Hello, Zhang.

On Fri, Apr 19, 2019 at 00:22:59 +0000, Zhang Haijun wrote:
> iedit.el(https://github.com/victorhge/iedit) is a multiple-cursors like
> package. It can setup more than one virtual cursors at different
> positions in the buffer. When you edit in the buffer, it clones changes
> at the main cursor to all other virtual cursors.

> The problem is that: Emacs lags too much when editing in c++-mode with
> iedit-mode on.  Profiler shows that cpu are most used by
> c-after-change.

The problem is in the function iedit-update-occurrences-2.  There,
inhibit-modification-hooks is bound to t, and the many changes are made.
The hook after-change-functions is called explicitly after each change.

But before-change-functions is not called in this loop.  This is a very
bad idea.  Unlike many modes, CC Mode has critical parts of its
functionality in the before-change-functions hook, and depends on this
hook and after-change-functions both being called for each change.

When CC Mode detects after-change-functions being called without
before-..., it enlarges the region to the whole buffer, calls
c-before-change with this enlarged region, finally proceding with the
rest of c-after-change.  It does this to protect its buffer's integrity.

So, the lag with the multiple cursors is being caused by processing the
entire buffer for each cursor, rather than just part of the buffer
involved.

So, why are you binding inhibit-modification-hooks to t and calling
after-change-functions this way?  Why not just let the modification hooks
run in the normal fashion?  What is it about before-change-functions
which is bad in iedit-mode?


> The related issue: https://github.com/victorhge/iedit/issues/83



> In GNU Emacs 26.2 (build 1, x86_64-apple-darwin17.7.0, NS appkit-1561.60 Version 10.13.6 (Build 17G6030))
>  of 2019-04-13 built on jundeMac
> Windowing system distributor 'Apple', version 10.3.1561
> Recent messages:
> For information about GNU Emacs and the GNU system, type C-h C-a.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Thu, 16 May 2019 15:47:02 GMT) Full text and rfc822 format available.

Message #23 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>,
 "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Thu, 16 May 2019 15:46:33 +0000

> 在 2019年5月16日,下午11:04,Alan Mackenzie <acm <at> muc.de> 写道:
> 
> The problem is in the function iedit-update-occurrences-2.  There,
> inhibit-modification-hooks is bound to t, and the many changes are made.
> The hook after-change-functions is called explicitly after each change.
> 
> But before-change-functions is not called in this loop.  This is a very
> bad idea.  Unlike many modes, CC Mode has critical parts of its
> functionality in the before-change-functions hook, and depends on this
> hook and after-change-functions both being called for each change.
> 
> When CC Mode detects after-change-functions being called without
> before-..., it enlarges the region to the whole buffer, calls
> c-before-change with this enlarged region, finally proceding with the
> rest of c-after-change.  It does this to protect its buffer's integrity.
> 

It seems that this leads too much redundant work.

> So, the lag with the multiple cursors is being caused by processing the
> entire buffer for each cursor, rather than just part of the buffer
> involved.
> 
> So, why are you binding inhibit-modification-hooks to t and calling
> after-change-functions this way?  Why not just let the modification hooks
> run in the normal fashion?  What is it about before-change-functions
> which is bad in iedit-mode?

I’m not the developer of iedit. I find a comment in the function iedit-update-occurrences-2:

                ;; todo: reconsider this change Quick fix for
                ;; multi-occur occur-edit-mode: multi-occur depend on
                ;; after-change-functions to update original
                ;; buffer. Since inhibit-modification-hooks is set to
                ;; non-nil, after-change-functions hooks are not going
                ;; to be called for the changes of other occurrences.
                ;; So run the hook here.



Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Thu, 16 May 2019 16:18:01 GMT) Full text and rfc822 format available.

Message #26 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Zhang Haijun <ccsmile2008 <at> outlook.com>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>,
 "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Thu, 16 May 2019 16:17:04 +0000
Hello, Zhang.

On Thu, May 16, 2019 at 15:46:33 +0000, Zhang Haijun wrote:


> > 在 2019年5月16日,下午11:04,Alan Mackenzie <acm <at> muc.de> 写道:

> > The problem is in the function iedit-update-occurrences-2.  There,
> > inhibit-modification-hooks is bound to t, and the many changes are made.
> > The hook after-change-functions is called explicitly after each change.

> > But before-change-functions is not called in this loop.  This is a very
> > bad idea.  Unlike many modes, CC Mode has critical parts of its
> > functionality in the before-change-functions hook, and depends on this
> > hook and after-change-functions both being called for each change.

> > When CC Mode detects after-change-functions being called without
> > before-..., it enlarges the region to the whole buffer, calls
> > c-before-change with this enlarged region, finally proceding with the
> > rest of c-after-change.  It does this to protect its buffer's integrity.


> It seems that this leads too much redundant work.

What iedit-mode is doing with after-change-functions is definitely wrong,
and will lead to misfunctioning in any major mode which uses
before-change-functions, as CC Mode does.

> > So, the lag with the multiple cursors is being caused by processing the
> > entire buffer for each cursor, rather than just part of the buffer
> > involved.

> > So, why are you binding inhibit-modification-hooks to t and calling
> > after-change-functions this way?  Why not just let the modification hooks
> > run in the normal fashion?  What is it about before-change-functions
> > which is bad in iedit-mode?

> I’m not the developer of iedit.

Would you please consider forwarding this email to the maintainer of
iedit.  Thanks!

> I find a comment in the function iedit-update-occurrences-2:

>                 ;; todo: reconsider this change Quick fix for
>                 ;; multi-occur occur-edit-mode: multi-occur depend on
>                 ;; after-change-functions to update original
>                 ;; buffer. Since inhibit-modification-hooks is set to
>                 ;; non-nil, after-change-functions hooks are not going
>                 ;; to be called for the changes of other occurrences.
>                 ;; So run the hook here.

I saw this comment too.  I had a look at the repository on github, and
this handling of after-change-functions has been there since at least
2012.  :-(

When I comment out the offending bits of code from
iedit-update-occurrences-2, like this:



--- iedit-lib.el~	2019-04-19 08:03:29.000000000 +0000
+++ iedit-lib.el	2019-05-16 15:58:27.158575662 +0000
@@ -490,7 +490,7 @@
 
 (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
   ""
-  (let ((inhibit-modification-hooks t)
+  (let (;; (inhibit-modification-hooks t)
         (offset (- beg (overlay-start occurrence)))
         (value (buffer-substring-no-properties beg end)))
     (save-excursion
@@ -509,10 +509,11 @@
                 ;; non-nil, after-change-functions hooks are not going
                 ;; to be called for the changes of other occurrences.
                 ;; So run the hook here.
-                (run-hook-with-args 'after-change-functions
-                                    beginning
-                                    ending
-                                    change))
+                ;; (run-hook-with-args 'after-change-functions
+                ;;                     beginning
+                ;;                     ending
+                ;;                     change)
+		)
               (iedit-move-conjoined-overlays another-occurrence)))
         ;; deletion
         (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
@@ -521,10 +522,11 @@
             (unless (eq beg end) ;; replacement
               (goto-char beginning)
               (insert-and-inherit value))
-            (run-hook-with-args 'after-change-functions
-                                beginning
-                                (+ beginning (- beg end))
-                                change)))))))
+            ;; (run-hook-with-args 'after-change-functions
+            ;;                     beginning
+            ;;                     (+ beginning (- beg end))
+            ;;                     change)
+	    ))))))
 
 (defun iedit-next-occurrence ()
   "Move forward to the next occurrence in the `iedit'.



, then iedit-mode and C++ Mode work well together.  In a C++ Mode test
buffer, just over 16k long, on a variable with 75 copies in it, I press
C-;.  On editing the copies of these variables, the response is now
instantaneous.

The question remaining is what was the problem which led to this mistaken
after-change-functions handling?  Is this problem still there?

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Fri, 17 May 2019 00:49:02 GMT) Full text and rfc822 format available.

Message #29 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>,
 "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Fri, 17 May 2019 00:48:18 +0000
>> I’m not the developer of iedit.
> 
> Would you please consider forwarding this email to the maintainer of
> iedit.  Thanks!
> 

Done.

> 
> I saw this comment too.  I had a look at the repository on github, and
> this handling of after-change-functions has been there since at least
> 2012.  :-(
> 
> When I comment out the offending bits of code from
> iedit-update-occurrences-2, like this:
> 
> 
> 
> --- iedit-lib.el~	2019-04-19 08:03:29.000000000 +0000
> +++ iedit-lib.el	2019-05-16 15:58:27.158575662 +0000
> @@ -490,7 +490,7 @@
> 
> (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
>   ""
> -  (let ((inhibit-modification-hooks t)
> +  (let (;; (inhibit-modification-hooks t)
>         (offset (- beg (overlay-start occurrence)))
>         (value (buffer-substring-no-properties beg end)))
>     (save-excursion
> @@ -509,10 +509,11 @@
>                 ;; non-nil, after-change-functions hooks are not going
>                 ;; to be called for the changes of other occurrences.
>                 ;; So run the hook here.
> -                (run-hook-with-args 'after-change-functions
> -                                    beginning
> -                                    ending
> -                                    change))
> +                ;; (run-hook-with-args 'after-change-functions
> +                ;;                     beginning
> +                ;;                     ending
> +                ;;                     change)
> +		)
>               (iedit-move-conjoined-overlays another-occurrence)))
>         ;; deletion
>         (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
> @@ -521,10 +522,11 @@
>             (unless (eq beg end) ;; replacement
>               (goto-char beginning)
>               (insert-and-inherit value))
> -            (run-hook-with-args 'after-change-functions
> -                                beginning
> -                                (+ beginning (- beg end))
> -                                change)))))))
> +            ;; (run-hook-with-args 'after-change-functions
> +            ;;                     beginning
> +            ;;                     (+ beginning (- beg end))
> +            ;;                     change)
> +	    ))))))
> 
> (defun iedit-next-occurrence ()
>   "Move forward to the next occurrence in the `iedit'.
> 
> 
> 
> , then iedit-mode and C++ Mode work well together.  In a C++ Mode test
> buffer, just over 16k long, on a variable with 75 copies in it, I press
> C-;.  On editing the copies of these variables, the response is now
> instantaneous.
> 

I tried your patch. And it works as you saied. No lags.




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Fri, 17 May 2019 01:20:02 GMT) Full text and rfc822 format available.

Message #32 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Amos Bird <amosbird <at> gmail.com>
To: debbugs-submit <at> debbugs.gnu.org
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Zhang Haijun <ccsmile2008 <at> outlook.com>
Subject: Re: bug#35316: 26.2;
 Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Fri, 17 May 2019 09:19:11 +0800
Hello, this patch works as expected. Is there any similar 
technique I can apply to undo-tree? After modifying hundreds of 
copies using iedit, doing undo/redo freezes for several minutes.

regards,
Amos

Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Zhang.
>
> On Thu, May 16, 2019 at 15:46:33 +0000, Zhang Haijun wrote:
>
>
>> > 在 2019年5月16日,下午11:04,Alan Mackenzie <acm <at> muc.de> 写道:
>
>> > The problem is in the function iedit-update-occurrences-2. 
>> > There,
>> > inhibit-modification-hooks is bound to t, and the many 
>> > changes are made.
>> > The hook after-change-functions is called explicitly after 
>> > each change.
>
>> > But before-change-functions is not called in this loop.  This 
>> > is a very
>> > bad idea.  Unlike many modes, CC Mode has critical parts of 
>> > its
>> > functionality in the before-change-functions hook, and 
>> > depends on this
>> > hook and after-change-functions both being called for each 
>> > change.
>
>> > When CC Mode detects after-change-functions being called 
>> > without
>> > before-..., it enlarges the region to the whole buffer, calls
>> > c-before-change with this enlarged region, finally proceding 
>> > with the
>> > rest of c-after-change.  It does this to protect its buffer's 
>> > integrity.
>
>
>> It seems that this leads too much redundant work.
>
> What iedit-mode is doing with after-change-functions is 
> definitely wrong,
> and will lead to misfunctioning in any major mode which uses
> before-change-functions, as CC Mode does.
>
>> > So, the lag with the multiple cursors is being caused by 
>> > processing the
>> > entire buffer for each cursor, rather than just part of the 
>> > buffer
>> > involved.
>
>> > So, why are you binding inhibit-modification-hooks to t and 
>> > calling
>> > after-change-functions this way?  Why not just let the 
>> > modification hooks
>> > run in the normal fashion?  What is it about 
>> > before-change-functions
>> > which is bad in iedit-mode?
>
>> I’m not the developer of iedit.
>
> Would you please consider forwarding this email to the 
> maintainer of
> iedit.  Thanks!
>
>> I find a comment in the function iedit-update-occurrences-2:
>
>>                 ;; todo: reconsider this change Quick fix for
>>                 ;; multi-occur occur-edit-mode: multi-occur 
>>                 depend on
>>                 ;; after-change-functions to update original
>>                 ;; buffer. Since inhibit-modification-hooks is 
>>                 set to
>>                 ;; non-nil, after-change-functions hooks are 
>>                 not going
>>                 ;; to be called for the changes of other 
>>                 occurrences.
>>                 ;; So run the hook here.
>
> I saw this comment too.  I had a look at the repository on 
> github, and
> this handling of after-change-functions has been there since at 
> least
> 2012.  :-(
>
> When I comment out the offending bits of code from
> iedit-update-occurrences-2, like this:
>
>
>
> --- iedit-lib.el~	2019-04-19 08:03:29.000000000 +0000
> +++ iedit-lib.el	2019-05-16 15:58:27.158575662 +0000
> @@ -490,7 +490,7 @@
>
>  (defun iedit-update-occurrences-2 (occurrence after beg end 
>  &optional change)
>    ""
> -  (let ((inhibit-modification-hooks t)
> +  (let (;; (inhibit-modification-hooks t)
>          (offset (- beg (overlay-start occurrence)))
>          (value (buffer-substring-no-properties beg end)))
>      (save-excursion
> @@ -509,10 +509,11 @@
>                  ;; non-nil, after-change-functions hooks are 
>                  not going
>                  ;; to be called for the changes of other 
>                  occurrences.
>                  ;; So run the hook here.
> -                (run-hook-with-args 'after-change-functions
> -                                    beginning
> -                                    ending
> -                                    change))
> +                ;; (run-hook-with-args 'after-change-functions
> +                ;;                     beginning
> +                ;;                     ending
> +                ;;                     change)
> +		)
>                (iedit-move-conjoined-overlays 
>                another-occurrence)))
>          ;; deletion
>          (dolist (another-occurrence (remove occurrence 
>          iedit-occurrences-overlays))
> @@ -521,10 +522,11 @@
>              (unless (eq beg end) ;; replacement
>                (goto-char beginning)
>                (insert-and-inherit value))
> -            (run-hook-with-args 'after-change-functions
> -                                beginning
> -                                (+ beginning (- beg end))
> -                                change)))))))
> +            ;; (run-hook-with-args 'after-change-functions
> +            ;;                     beginning
> +            ;;                     (+ beginning (- beg end))
> +            ;;                     change)
> +	    ))))))
>
>  (defun iedit-next-occurrence ()
>    "Move forward to the next occurrence in the `iedit'.
>
>
>
> , then iedit-mode and C++ Mode work well together.  In a C++ 
> Mode test
> buffer, just over 16k long, on a variable with 75 copies in it, 
> I press
> C-;.  On editing the copies of these variables, the response is 
> now
> instantaneous.
>
> The question remaining is what was the problem which led to this 
> mistaken
> after-change-functions handling?  Is this problem still there?


--
Amos Bird
amosbird <at> gmail.com




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Fri, 17 May 2019 10:02:01 GMT) Full text and rfc822 format available.

Message #35 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Amos Bird <amosbird <at> gmail.com>
Cc: 35316 <at> debbugs.gnu.org, ccsmile2008 <at> outlook.com
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Fri, 17 May 2019 10:01:18 +0000
Hello, Amos.

On Fri, May 17, 2019 at 09:19:11 +0800, Amos Bird wrote:

> Hello, this patch works as expected. Is there any similar 
> technique I can apply to undo-tree? After modifying hundreds of 
> copies using iedit, doing undo/redo freezes for several minutes.

Whoa there!

Are we still talking about C++ Mode (or one of the other modes in the CC
Mode family)?  How big is your file?  Can you characterise it in any way?
For example, does it contain lots of, or big, raw strings?

I noticed yesterday on a C++ test file with a very long raw string, that
although editing copies of a string segment (using iedit) was fast, undo
afterwards was very slow indeed (~1 minute).

So, perhaps your problem is the same as mine.  Perhaps you have
encountered a different problem.  It seems I have more work to do on this
in any case.

So, details, please!

> regards,
> Amos

[ .... ]

> --
> Amos Bird
> amosbird <at> gmail.com

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Fri, 17 May 2019 17:36:02 GMT) Full text and rfc822 format available.

Message #38 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Amos Bird <amosbird <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 35316 <at> debbugs.gnu.org, ccsmile2008 <at> outlook.com
Subject: Re: bug#35316: 26.2;
 Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Sat, 18 May 2019 01:35:58 +0800
Hi Alan!

> Are we still talking about C++ Mode

Yeah it's c++ mode but it can also be reproduced with c mode.
The minute long frozen is caused mainly by the lsp-mode, howeveer
it's still laggy after turning lsp off.

> How big is your file?  Can you characterise it in any way?

You can try emacs/src/xdisp.c . iediting all "make_fixnum",
turning them into "make_fixnum_why_undo_redo_is_so_slow", and 
undo.
It's about 10-20 seconds freezing time here.

> It seems I have more work to do on this in any case.

Looking forward to it!

regards,

--
Amos Bird
amosbird <at> gmail.com




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 19 May 2019 11:41:02 GMT) Full text and rfc822 format available.

Message #41 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Amos Bird <amosbird <at> gmail.com>, Zhang Haijun <ccsmile2008 <at> outlook.com>
Cc: 35316 <at> debbugs.gnu.org
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Sun, 19 May 2019 11:40:19 +0000
Hello, Amos and Zhang.

First thing, apologies for the patch I sent you a few days ago.  It was
based on a misunderstanding, and it is total garbage!

The misunderstanding was the assumption that
`inhibit-modification-hooks' would be nil on entry to
`iedit-update-occurrences-2', and that leaving it nil would allow the
`before-change-functions' and `after-change-functions' hooks to run
normally.

In actual fact `inhibit-modification-hooks' is t at that point, and
cannot successfully be bound to nil.  So, both `before-change-functions'
and `after-change-functions' need to be called explicitly for successful
processing.

So, please disregard that previous patch from me, and try out instead
the patch below.  In C++ Mode it is somewhat slower, since it is
actually doing the change processing, but not unusably so.  Undo seems
to be working a bit faster too, though it is often not instantaneous as
one would wish (see below).

On Sat, May 18, 2019 at 01:35:58 +0800, Amos Bird wrote:

> Hi Alan!

> > Are we still talking about C++ Mode

> Yeah it's c++ mode but it can also be reproduced with c mode.
> The minute long frozen is caused mainly by the lsp-mode, howeveer
> it's still laggy after turning lsp off.

> > How big is your file?  Can you characterise it in any way?

> You can try emacs/src/xdisp.c . iediting all "make_fixnum",
> turning them into "make_fixnum_why_undo_redo_is_so_slow", and 
> undo.
> It's about 10-20 seconds freezing time here.

When I do this now (with the patch in place), undo works in two stages,
taking about 0.4s and 2.4s respectively on my machine.

> > It seems I have more work to do on this in any case.

As a matter of interest, could one of you please give me the name and
email address of the iedit-mode maintainer.  I haven't got a github
account, and don't want to create one, so I don't think I can get in
touch with her/him that way.

> Looking forward to it!

OK, here goes!



--- iedit-lib.el.orig	2019-05-19 10:55:31.681959998 +0000
+++ iedit-lib.el	2019-05-19 11:08:27.549988930 +0000
@@ -490,7 +490,9 @@
 
 (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
   ""
-  (let ((inhibit-modification-hooks t)
+  (let (;; (inhibit-modification-hooks t)
+        ;; Note: `inhibit-modification-hook' will already be non-nil when this
+	;; function is called.  Setting it to nil here doesn't work.
         (offset (- beg (overlay-start occurrence)))
         (value (buffer-substring-no-properties beg end)))
     (save-excursion
@@ -501,6 +503,9 @@
                    (ending (+ beginning (- end beg))))
               (when (not (eq another-occurrence occurrence))
                 (goto-char beginning)
+		(run-hook-with-args 'before-change-functions
+				    beginning
+				    (+ beginning change))
                 (insert-and-inherit value)
                 ;; todo: reconsider this change Quick fix for
                 ;; multi-occur occur-edit-mode: multi-occur depend on
@@ -517,13 +522,17 @@
         ;; deletion
         (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
           (let ((beginning (+ (overlay-start another-occurrence) offset)))
+	    (goto-char beginning)
+	    (run-hook-with-args 'before-change-functions
+				beginning
+				(+ beginning change))
             (delete-region beginning (+ beginning change))
             (unless (eq beg end) ;; replacement
               (goto-char beginning)
               (insert-and-inherit value))
             (run-hook-with-args 'after-change-functions
                                 beginning
-                                (+ beginning (- beg end))
+                                (+ beginning (- end beg))
                                 change)))))))
 
 (defun iedit-next-occurrence ()


> regards,

> --
> Amos Bird
> amosbird <at> gmail.com

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 19 May 2019 13:21:01 GMT) Full text and rfc822 format available.

Message #44 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: Amos Bird <amosbird <at> gmail.com>, 35316 <at> debbugs.gnu.org,
 Zhang Haijun <ccsmile2008 <at> outlook.com>
Subject: Re: bug#35316: 26.2;
 Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Sun, 19 May 2019 09:20:16 -0400
Alan Mackenzie <acm <at> muc.de> writes:

>  (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
>    ""
> -  (let ((inhibit-modification-hooks t)
> +  (let (;; (inhibit-modification-hooks t)
> +        ;; Note: `inhibit-modification-hook' will already be non-nil when this
> +	;; function is called.  Setting it to nil here doesn't work.

By "doesn't work", do you mean that it would trigger an infloop?
Would something like this work:

    (defvar iedit-inhibit-update nil)

    (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
     ...
     ;; Let other modification hooks run, but don't recurse infinitely.
     (unless iedit-inhibit-update
       (let ((inhibit-modification-hooks nil)
             (iedit-inhibit-update t))
       ...

See also Bug#25111 "How modification-hooks let-bind
inhibit-modification-hooks?" https://debbugs.gnu.org/25111




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 19 May 2019 13:52:02 GMT) Full text and rfc822 format available.

Message #47 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Alan Mackenzie <acm <at> muc.de>, Amos Bird <amosbird <at> gmail.com>
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Sun, 19 May 2019 13:51:49 +0000
[Message part 1 (text/plain, inline)]
The author of iedit seems not too active(not everyday) on github. Here is the email on his account info of github: victorhge <at> gmail.com.

However, the gmail is blocked in china(the page shows that he is in china). I don't known if he can read the mail.

Besides iedit, I tried with multiple-cursors(https://github.com/magnars/multiple-cursors.el) with the similar editing operation. It works well(no obvious lags).

获取 Outlook for Android<https://aka.ms/ghei36>

________________________________
From: Alan Mackenzie <acm <at> muc.de>
Sent: Sunday, May 19, 2019 7:40:19 PM
To: Amos Bird; Zhang Haijun
Cc: 35316 <at> debbugs.gnu.org
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with iedit-mode on

Hello, Amos and Zhang.

First thing, apologies for the patch I sent you a few days ago.  It was
based on a misunderstanding, and it is total garbage!

The misunderstanding was the assumption that
`inhibit-modification-hooks' would be nil on entry to
`iedit-update-occurrences-2', and that leaving it nil would allow the
`before-change-functions' and `after-change-functions' hooks to run
normally.

In actual fact `inhibit-modification-hooks' is t at that point, and
cannot successfully be bound to nil.  So, both `before-change-functions'
and `after-change-functions' need to be called explicitly for successful
processing.

So, please disregard that previous patch from me, and try out instead
the patch below.  In C++ Mode it is somewhat slower, since it is
actually doing the change processing, but not unusably so.  Undo seems
to be working a bit faster too, though it is often not instantaneous as
one would wish (see below).

On Sat, May 18, 2019 at 01:35:58 +0800, Amos Bird wrote:

> Hi Alan!

> > Are we still talking about C++ Mode

> Yeah it's c++ mode but it can also be reproduced with c mode.
> The minute long frozen is caused mainly by the lsp-mode, howeveer
> it's still laggy after turning lsp off.

> > How big is your file?  Can you characterise it in any way?

> You can try emacs/src/xdisp.c . iediting all "make_fixnum",
> turning them into "make_fixnum_why_undo_redo_is_so_slow", and
> undo.
> It's about 10-20 seconds freezing time here.

When I do this now (with the patch in place), undo works in two stages,
taking about 0.4s and 2.4s respectively on my machine.

> > It seems I have more work to do on this in any case.

As a matter of interest, could one of you please give me the name and
email address of the iedit-mode maintainer.  I haven't got a github
account, and don't want to create one, so I don't think I can get in
touch with her/him that way.

> Looking forward to it!

OK, here goes!



--- iedit-lib.el.orig   2019-05-19 10:55:31.681959998 +0000
+++ iedit-lib.el        2019-05-19 11:08:27.549988930 +0000
@@ -490,7 +490,9 @@

 (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
   ""
-  (let ((inhibit-modification-hooks t)
+  (let (;; (inhibit-modification-hooks t)
+        ;; Note: `inhibit-modification-hook' will already be non-nil when this
+       ;; function is called.  Setting it to nil here doesn't work.
         (offset (- beg (overlay-start occurrence)))
         (value (buffer-substring-no-properties beg end)))
     (save-excursion
@@ -501,6 +503,9 @@
                    (ending (+ beginning (- end beg))))
               (when (not (eq another-occurrence occurrence))
                 (goto-char beginning)
+               (run-hook-with-args 'before-change-functions
+                                   beginning
+                                   (+ beginning change))
                 (insert-and-inherit value)
                 ;; todo: reconsider this change Quick fix for
                 ;; multi-occur occur-edit-mode: multi-occur depend on
@@ -517,13 +522,17 @@
         ;; deletion
         (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
           (let ((beginning (+ (overlay-start another-occurrence) offset)))
+           (goto-char beginning)
+           (run-hook-with-args 'before-change-functions
+                               beginning
+                               (+ beginning change))
             (delete-region beginning (+ beginning change))
             (unless (eq beg end) ;; replacement
               (goto-char beginning)
               (insert-and-inherit value))
             (run-hook-with-args 'after-change-functions
                                 beginning
-                                (+ beginning (- beg end))
+                                (+ beginning (- end beg))
                                 change)))))))

 (defun iedit-next-occurrence ()


> regards,

> --
> Amos Bird
> amosbird <at> gmail.com

--
Alan Mackenzie (Nuremberg, Germany).
[Message part 2 (text/html, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 19 May 2019 14:27:02 GMT) Full text and rfc822 format available.

Message #50 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Noam Postavsky <npostavs <at> gmail.com>
Cc: Amos Bird <amosbird <at> gmail.com>, 35316 <at> debbugs.gnu.org,
 Zhang Haijun <ccsmile2008 <at> outlook.com>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Sun, 19 May 2019 14:26:15 +0000
Hello, Noam.

On Sun, May 19, 2019 at 09:20:16 -0400, Noam Postavsky wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> >  (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
> >    ""
> > -  (let ((inhibit-modification-hooks t)
> > +  (let (;; (inhibit-modification-hooks t)
> > +        ;; Note: `inhibit-modification-hook' will already be non-nil when this
> > +	;; function is called.  Setting it to nil here doesn't work.

> By "doesn't work", do you mean that it would trigger an infloop?

It would trigger a binding stack overflow.  (It did when I tried it.)
iedit-update-occurrences-2 is (a subroutine of) the handler for the
modification-hooks property of the overlay at point.  It performs buffer
modifications on the other overlays.  If inhibit-modification-hooks is
bound to nil, these other modifications in their turn cause
iedit-update-occurrences-2 to get called recursively.

> Would something like this work:

>     (defvar iedit-inhibit-update nil)

>     (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
>      ...
>      ;; Let other modification hooks run, but don't recurse infinitely.
>      (unless iedit-inhibit-update
>        (let ((inhibit-modification-hooks nil)
>              (iedit-inhibit-update t))
>        ...

I haven't actually tried it, but gut feeling says this approach might be
problematic.  It could end up inserting into/deleting from each overlay
many times.  Or some of the insertions/deletions wouldn't get the change
hooks called for them, depending on how the rest of the code is split
into the two "..."s.

It might also be even less clean than the explicit calls to
before/after-change-functions.

> See also Bug#25111 "How modification-hooks let-bind
> inhibit-modification-hooks?" https://debbugs.gnu.org/25111

Thanks.  I was considering raising the same issue in a bug myself.
#25111 is still open, I think (the web interface doesn't explicitly
say), and I think the doc is objectively wrong.  It doesn't state that
when modification-hooks is called, inhibit-modification-hooks has
already been set to non-nil.  That was what caught me out when I wrote
the previous (garbage) patch on ?Thursday.

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 19 May 2019 17:42:02 GMT) Full text and rfc822 format available.

Message #53 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: Amos Bird <amosbird <at> gmail.com>, 35316 <at> debbugs.gnu.org,
 Zhang Haijun <ccsmile2008 <at> outlook.com>
Subject: Re: bug#35316: 26.2;
 Emacs lags in c++-mode buffer when editing with iedit-mode on
Date: Sun, 19 May 2019 13:41:14 -0400
Alan Mackenzie <acm <at> muc.de> writes:

>> Would something like this work:
>
>>     (defvar iedit-inhibit-update nil)
>
>>     (defun iedit-update-occurrences-2 (occurrence after beg end &optional change)
>>      ...
>>      ;; Let other modification hooks run, but don't recurse infinitely.
>>      (unless iedit-inhibit-update
>>        (let ((inhibit-modification-hooks nil)
>>              (iedit-inhibit-update t))
>>        ...
>
> I haven't actually tried it, but gut feeling says this approach might be
> problematic.  It could end up inserting into/deleting from each overlay
> many times.  Or some of the insertions/deletions wouldn't get the change
> hooks called for them, depending on how the rest of the code is split
> into the two "..."s.

Sorry, it was a bit unclear, the first "..." was just intended to be the
docstring.  I.e., the code I put in there should be at the top-level of
the function, and wrap the rest of the code.

> It might also be even less clean than the explicit calls to
> before/after-change-functions.

Although it misses text property and overlay change hooks.

>> See also Bug#25111 "How modification-hooks let-bind
>> inhibit-modification-hooks?" https://debbugs.gnu.org/25111
>
> Thanks.  I was considering raising the same issue in a bug myself.
> #25111 is still open, I think (the web interface doesn't explicitly
> say),

Yes, it's open.

> and I think the doc is objectively wrong.  It doesn't state that
> when modification-hooks is called, inhibit-modification-hooks has
> already been set to non-nil.  That was what caught me out when I wrote
> the previous (garbage) patch on ?Thursday.

Yeah, it's a tricky case.  The docs are definitely not adequate.





Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Mon, 04 Nov 2019 03:17:02 GMT) Full text and rfc822 format available.

Message #56 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Zhang Haijun <ccsmile2008 <at> outlook.com>
To: Alan Mackenzie <acm <at> muc.de>, Amos Bird <amosbird <at> gmail.com>
Cc: "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing with
 iedit-mode on
Date: Mon, 4 Nov 2019 03:16:19 +0000
Hello Alan.

Your final patch works well until now. Thank you very much.


Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#35316; Package emacs,cc-mode. (Sun, 20 Sep 2020 18:01:01 GMT) Full text and rfc822 format available.

Message #59 received at 35316 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Zhang Haijun <ccsmile2008 <at> outlook.com>
Cc: Alan Mackenzie <acm <at> muc.de>, Amos Bird <amosbird <at> gmail.com>,
 "35316 <at> debbugs.gnu.org" <35316 <at> debbugs.gnu.org>
Subject: Re: bug#35316: 26.2; Emacs lags in c++-mode buffer when editing
 with iedit-mode on
Date: Sun, 20 Sep 2020 19:59:43 +0200
Zhang Haijun <ccsmile2008 <at> outlook.com> writes:

> Hello Alan.
>
> Your final patch works well until now. Thank you very much.

It looks like Alan's iedit patch fixed the problem, so there doesn't
seem to be anything more to be done in this bug report, and I'm closing it.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Added tag(s) fixed. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sun, 20 Sep 2020 18:01:02 GMT) Full text and rfc822 format available.

bug marked as fixed in version 28.1, send any further explanations to 35316 <at> debbugs.gnu.org and Zhang Haijun <ccsmile2008 <at> outlook.com> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sun, 20 Sep 2020 18:01:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 19 Oct 2020 11:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 4 years and 35 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.