emacs打开部分c++文件十分卡顿

使用emacs打开c++文件时,有些文件会卡顿 移动卡顿;编辑卡顿;甚至弹出的minibuffer都是先在中央跳动一下,再显示在底部 而这种卡顿针对某个文件,其他的文件不会有问题 求教 (环境:archlinux) (嫌疑犯:lsp-mode, eaf等)

二分注释法排除问题,结合emacs -Q一起排查,猜没用

找到了,是highlight-indent-guides-mode,谢谢

问题复现了

emacs -Q启动仍旧卡顿

是emacs本身的问题吗?

程序代码:

#include <iostream>
#include <vector>

#define MAX 10000

void merge(std::vector<int> array, int p, int q, int r) {
  int len_1 = q - p + 1;
  int len_2 = r - q;
  int a = 0;
  int b = 0;
  std::vector<int> left_array(len_1 + 2, 0);
  std::vector<int> right_array(len_2 + 2, 0);
  for (int i = 0; i < len_1; ++i) {
    left_array[i] = array[p + i - 1];
  }
  for (int i = 0; i < len_2; ++i) {
    right_array[i] = array[q + i];
  }
  left_array[len_1 + 1] = MAX;
  right_array[len_2 + 1] = MAX;
  for (int i = p; i < r + 1; ++i) {
    if (left_array[a] <= right_array[b]) {
      array[i] = left_array[a];
      ++a;
    } else {
      array[i] = right_array[b];
      ++b;
    }
  }
}

void merge_sort(std::vector<int> array, int p, int r) {
  if (p < r) {
    int q = (p + r) / 2;
    merge_sort(array, p, q);
    merge_sort(array, q + 1, r);
    merge(array, p, q, r);
  }
}

int main() {
  std::vector<int> array = {3, 1, 2, 6, 4, 5};
  merge_sort(array, 0, array.size() - 1);
  for (auto i : array) {
    std::cout << i << "\n";
  }
  return 0;
}

buffer中一旦出现merge代码部分就会卡顿

代码定位出来了 是因为有了 for (int i = p; i < r + 1; ++i) {这句代码才卡顿的

1 个赞

r+1这里的问题,i < r + 1是触发了emacs的什么机制吗

回下帖:你提一下issus,但我感觉这应该是emacs内部的问题

我这边 Emacs 29 也复现了… CPU 100%

2952  62% - redisplay_internal (C function)
        2936  62%  - jit-lock-function
        2936  62%   - jit-lock-fontify-now
        2920  62%    - jit-lock--run-functions
        2920  62%     - run-hook-wrapped
        2920  62%      - #<compiled 0x19b62a583670403d>
        2920  62%       - font-lock-fontify-region
        2920  62%        - c-font-lock-fontify-region
        2605  55%         - font-lock-default-fontify-region
        2534  53%          - font-lock-fontify-keywords-region
        1339  28%           - c-font-lock-declarations
        1317  27%            - c-find-decl-spots
         593  12%             + #<compiled 0x62f8c10afa44432>
         582  12%             + c-bs-at-toplevel-p

profile 显示是 cc-mode 的 fontification 有点问题。

如果不介意的话,我就把这个 bug 报到上游去了?

1 个赞

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=51631

bug 跟踪单

3 个赞

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=51692

对应的 patch。

diff -r 05fd00cb5937 cc-engine.el
--- a/cc-engine.el	Sat Oct 30 15:57:26 2021 +0000
+++ b/cc-engine.el	Thu Nov 11 18:47:47 2021 +0000
@@ -6838,6 +6838,13 @@
 (defvar c-found-types nil)
 (make-variable-buffer-local 'c-found-types)
 
+;; Dynamically bound variable that instructs `c-forward-type' to
+;; record the ranges of types that only are found.  Behaves otherwise
+;; like `c-record-type-identifiers'.  Also when this variable is non-nil,
+;; `c-fontify-new-found-type' doesn't get called (yet) for the purported
+;; type.
+(defvar c-record-found-types nil)
+
 (defsubst c-clear-found-types ()
   ;; Clears `c-found-types'.
   (setq c-found-types
@@ -6851,7 +6858,10 @@
   (let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
     (unless (gethash type c-found-types)
       (puthash type t c-found-types)
-      (when (and (eq (string-match c-symbol-key type) 0)
+      (when (and (not c-record-found-types) ; Only call `c-fontify-new-fount-type'
+					; when we haven't "bound" c-found-types
+					; to itself in c-forward-<>-arglist.
+		 (eq (string-match c-symbol-key type) 0)
 		 (eq (match-end 0) (length type)))
 	(c-fontify-new-found-type type)))))
 
@@ -8248,11 +8258,6 @@
 	   (setq c-record-ref-identifiers
 		 (cons range c-record-ref-identifiers))))))
 
-;; Dynamically bound variable that instructs `c-forward-type' to
-;; record the ranges of types that only are found.  Behaves otherwise
-;; like `c-record-type-identifiers'.
-(defvar c-record-found-types nil)
-
 (defmacro c-forward-keyword-prefixed-id (type)
   ;; Used internally in `c-forward-keyword-clause' to move forward
   ;; over a type (if TYPE is 'type) or a name (otherwise) which
@@ -8480,6 +8485,11 @@
 		(c-forward-<>-arglist-recur all-types)))
 	(progn
 	  (when (consp c-record-found-types)
+	    (let ((cur c-record-found-types))
+	      (while (consp (car-safe cur))
+		(c-fontify-new-found-type
+		 (buffer-substring-no-properties (caar cur) (cdar cur)))
+		(setq cur (cdr cur))))
 	    (setq c-record-type-identifiers
 		  ;; `nconc' doesn't mind that the tail of
 		  ;; `c-record-found-types' is t.
@@ -9203,6 +9213,12 @@
 
 		(when (and (eq res t)
 			   (consp c-record-found-types))
+		  ;; Cause the confirmed types to get fontified.
+		  (let ((cur c-record-found-types))
+		    (while (consp (car-safe cur))
+		      (c-fontify-new-found-type
+		       (buffer-substring-no-properties (caar cur) (cdar cur)))
+		      (setq cur (cdr cur))))
 		  ;; Merge in the ranges of any types found by the second
 		  ;; `c-forward-type'.
 		  (setq c-record-type-identifiers
diff -r 05fd00cb5937 cc-fonts.el
--- a/cc-fonts.el	Sat Oct 30 15:57:26 2021 +0000
+++ b/cc-fonts.el	Thu Nov 11 18:47:47 2021 +0000
@@ -105,6 +105,7 @@
 (cc-bytecomp-defun c-font-lock-objc-method)
 (cc-bytecomp-defun c-font-lock-invalid-string)
 (cc-bytecomp-defun c-before-context-fl-expand-region)
+(cc-bytecomp-defun c-font-lock-fontify-region)
 
 
 ;; Note that font-lock in XEmacs doesn't expand face names as
@@ -2431,6 +2432,7 @@
 (defun c-force-redisplay (start end)
   ;; Force redisplay immediately.  This assumes `font-lock-support-mode' is
   ;; 'jit-lock-mode.  Set the variable `c-re-redisplay-timer' to nil.
+  (save-excursion (c-font-lock-fontify-region start end))
   (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
   (setq c-re-redisplay-timer nil))
 
@@ -2458,7 +2460,6 @@
 	    (dolist (win-boundary window-boundaries)
 	      (when (and (< (match-beginning 0) (cdr win-boundary))
 			 (> (match-end 0) (car win-boundary))
-			 (c-get-char-property (match-beginning 0) 'fontified)
 			 (not c-re-redisplay-timer))
 		(setq c-re-redisplay-timer
 		      (run-with-timer 0 nil #'c-force-redisplay

我试用了一下,基本没啥问题了。可以等待 Alan 提交对应的 patch


patch 已提交,可以重新 build Emacs 了。

10 个赞

我这边也是这样,