自 emacs触发before-change-hook和after-change-hook过于频繁后继续讨论

在使用irony补全c-cpp头文件时候遇到的问题 继续讨论:

我不是很懂这两句话, 追踪每一次更改都是有意义的, 为什么你又要说emacs在其中浪费了太多时间呢?

另一方面, 就拿flycheck检查和更新词法高亮来说, 这两个东西完全可以等用户打完字然后一次性给更新了, 为什么要追踪每一次的更改呢

举个真实的例子,几个月前,emacs的cc-mode被报了一个bug:用户选中很大一块区域,运行comment-region,发现会卡顿很长时间(可能几分钟),用户只是想把这个区域的代码注释掉而已。

原因是comment-region内部是逐行处理的,每注释一行触发一次change-hook(关联区域是一行),来执行那些hook函数,这样累加起来竟然导致了几分钟的卡顿,很夸张。

后来提交了一个解决方法,就是把每行的change-hook省掉,等整个区域都处理完之后,触发一次change-hook,而这个change的区域(change-hook关联的区域)是把所有注释掉的行合并起来组成的一个大区域。这样卡顿就消失了。

就是说,change-hook是可以合并的,只要关联的区域(change的区域)计算好了,能包含所有改变的区域即可,这样追踪一次与追踪每一次是等效的。当然这个区域不是越大越好,要尽量小。

flycheck是可以,可以结合定时器来做,它是整个buffer处理的,不需要精确知道buffer局部的具体变化。但是有些不行,比如cc-mode维护内部状态的hook(c-after-change这些,而这个是大头)。

用iedit-mode时候,经常卡顿,打一个字卡接近1秒,profile之后发现也是c-after-change在占cpu。

iedit-mode类似mutiple-cursor,多光标输入

这些hook一方面导致卡顿,另一方面有兼容性问题,像yasnippet展开过程中,用户修改占位符内容时候,这些hook处理函数可能会破坏yasnippet的内部状态,要仔细兼容才行。

归根结底一句话 : 自己的配置自己写