有经验的大神帮看看这是不是Emacs引入的问题

之前每隔一段时间我都会从emacs mirror编译一个native+pgtk版本和nox版本,分别在个人laptop上和工作中用。

在8月25之后,编译的版本出了一些性能问题,当时先搁置了,后来又编了几个版本也还是有问题。所以一直锁在8月25之前的版本。

最近几天又重新编译了一次29.0.50. 发现问题还在, 并且试了下archlinuxcn 的emacs-git, 一样有这个性能问题, 所以我决定认真排查一下, 发现可能是emacs的lisp/thingatpt.el:thing-at-point的修改引入的问题。

问题是这样的:在一个buffer里,移动光标,会变得越来越卡顿,最后几乎无法工作。buffer 的mode有 symbol-overlay-mode 和 lsp-ui-doc-mode, 看图:

thingatpt

↑ 出问题版本的cpu profiler

thingatpt1

↑ 关掉lsp-ui-doc-mode的cpu profiler

thingatpt2

↑ 关掉symbol-overlay-mode的cpu profiler

thingatpt0

↑ 正常流畅的情况下cpu profiler

我寻思没人遇到类似的问题吗? 难道这么多emacser就只有我有这个问题?

master 的commits 是这个 7db376e560448e61485ba054def8c82b21f33d6a 及其之后的commits, 看了下lisp/thingatpt.el改动不算多, 但感觉就是改动引入的问题. 有经验的大神帮忙看看, 非常感谢.

另外,将有问题版本的thingatpt.el 替换成老版本的thingatpt.el,问题就消失了。

具体出错的 commit 可以麻烦您 bisect 一下吗?谢谢。

从没遇到过这个问题。

  • macOS 10.13.6
  • Emacs 5640b055d6962bbf54958e9c2355bd21f763967d (2021-12-13)
  • symbol-overlay 8629a4ddbe95d42c39ce817d724877deb1984ba1 (20210906.614)

7db376e560448e61485ba054def8c82b21f33d6a 并没做什么实质上的修改,只不过是在原来的代码上套了一层:

(save-restriction
  (narrow-to-region (field-beginning) (field-end))
  ...)

你可以试试创建一份最小配置或者用 emacsq.sh 看能否重现:

emacsq.sh -P symbol-overlay -M symbol-overlay-mode

确认了在我这儿就是下面这个commit开始出问题, thing-at-point开销特别大。

commit 7db376e560448e61485ba054def8c82b21f33d6a Author: Lars Ingebrigtsen [email protected] Date: Wed Aug 25 18:04:43 2021 +0200

Make thingatpt respect fields

* lisp/thingatpt.el (thing-at-point): Make thingatpt respect
fields (bug#9454).

用你这个emacsq.sh 复现了的。

  • ArchLinux & Ubuntu 16.04 Emacs 29.0.50 2021-12-15
  • symbol-overlay 20210906.614

thingatpt_arch0

~/.emacs.d/elpa 下的 *.elc 有重新编译过吗?

.elc 都删掉了的, thingatpt.elc也是删掉了的。

请 report-emacs-bug(report 要从 28.0.90 的 Emacs 发送)。

这个提交我感觉有点问题。thing-at-point常用于循环内部。比如拼写检查。性能很关键。不应该再叠加加新功能了。

的确存在这方面的疑虑。

但是我一直都是用开发板,从 27 到 28 (pretest 之前) 到 29 都很顺畅,没有感觉到性能上的损失。

不过我又去跑了一遍 benchmark,发现 27 的性能比之前的版本略有下降,28 比 27 下降了 4 倍,29 又恢复到 27 的水平:

(with-emacs-25.1
  (require 'benchmark)
  (save-excursion (insert "foo"))
  (benchmark-run 100000 (thing-at-point 'symbol))) ;; => (2.114287 67 0.8883600000000001)

(with-emacs-26.1
  (require 'benchmark)
  (save-excursion (insert "foo"))
  (benchmark-run 100000 (thing-at-point 'symbol))) ;; => (2.124073 59 0.8687790000000001)

(with-emacs-27.1
  (require 'benchmark)
  (save-excursion (insert "foo"))
  (benchmark-run 100000 (thing-at-point 'symbol))) ;; => (2.6949899999999998 69 1.222715)

(with-emacs-28.1-pretest
  (require 'benchmark)
  (save-excursion (insert "foo"))
  (benchmark-run 100000 (thing-at-point 'symbol))) ;; => (8.696676 47 4.338927)

(with-emacs-29.0-2021-1213
  (require 'benchmark)
  (save-excursion (insert "foo"))
  (benchmark-run 100000 (thing-at-point 'symbol))) ;; => (2.387791 53 1.075944)
2 个赞

buffer 的 current position 得动起来才能测出问题

save-restriction 中不该造成 display 的变化,最好别运行 message 什么的。

这是 7db376e560448e61485ba054def8c82b21f33d6a commit之前的 thingatpt.el 的 cpu profiler-report

@gniuk 请问您报了这个bug了吗?

我应该也遇到了这个问题,编译的最新master分支,带pgtk。 (513fe2d6ff9808d54e9a9ff6eb82ef1518d4d6ad).

在haskell-mode的buffer里移动光标会越来越卡,最后卡到鼠标转圈圈(这表示是在gc吗?),转一会儿圈后会变得没那么卡,再移动光标后又会卡,如此往复。

但我buffer里没有开symbol-overlay-mode,有lsp-mode。

我们遇到问题的Emacs都开了pgtk编译选项,难道是pgtk的问题?我现在编译一个不带pgtk的测一下。

bug report应该是这个吧:https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-12/msg01398.html

对,是这个bug report。

这里也可以看到 #52593 - 28.0.90; (thing-at-point thing) has so much overhead since commit 7db376e560448e61485ba054def8c82b21f33d6a - GNU bug report logs

是thing-at-point 引入 (field-beginning)和(field-end) 导致的性能问题。Eli Zaretskii 和 Lars Ingebrigtsen 已经在商讨怎么处理了,目前还没结论。

没symbol-overlay-mode的话,看是不是有lsp-ui-doc-mode, 有的话你直接 M-x lsp-ui-doc-mode 关掉它,再移动光标看看卡不卡。

我的emacs也存在同样的问题。

可是我也没开lsp-ui-doc-mode,开profiler看到的占用资源最大的都是很普通很常见的函数,其中没有thing-at-point。 我再捉捉虫罢。