【发布时间】:2014-09-26 08:32:44
【问题描述】:
以下名为 my-modeline-face-function 的函数会导致 Emacs 暂停大约半秒到一整秒,我正在寻找一些建议以显着提高速度。
看起来不多,但是这个功能用的挺多的。例如,每次我启用多光标模式(又名 mc 模式)时,我都会在开始工作之前摆弄拇指——退出多光标模式时也会发生同样的事情。
在函数末尾添加(redisplay t) 并不会提高速度。
在这个函数后面使用(force-mode-line-update)不会提高速度。
(defun my-modeline-face-function ()
(cond
((minibufferp)
(set-face-attribute 'mode-line nil :height 140 :foreground "gray70"
:background "black" :box '(:line-width 1 :color "black"))
(set-face-attribute 'minibuffer-prompt nil :background "black"
:foreground "cyan" :bold t)
(set (make-local-variable 'face-remapping-alist)
'((default :background "black" :foreground "yellow"))))
(save-as-variable
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "#eab700" :box nil))
(insert-variable
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "orange" :box nil))
((or multi-extract-variable multi-attach-variable)
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "magenta" :box nil))
(open-with-variable
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "ForestGreen" :box nil))
(mc-mode
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "cyan" :box nil))
(isearch-mode
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "yellow" :box nil))
((eq major-mode 'lawlist-calculator-mode)
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "firebrick" :box nil))
(t
(set-face-attribute 'mode-line nil :height 140
:foreground "black" :background "gray70" :box nil)
(set-face-attribute 'minibuffer-prompt nil
:background "black" :foreground "white"))) )
编辑(2014 年 8 月 5 日):
● 使用measure-time 宏(即http://lists.gnu.org/archive/html/help-gnu-emacs/2008-06/msg00087.html),我验证了set-face-attribute 中函数internal-set-lisp-face-attribute 的运行时间仅在几分之一秒内发生。但是,我需要一整秒才能看到视觉效果。无论是函数的初始调用还是同一缓冲区内的后续调用,都是如此。
● 缓冲区内第一次调用face-remapping-alist,视觉效果需要整整一秒才能看到。但是,在同一缓冲区内使用face-remapping-alist 的后续调用会在几分之一秒内发生。在第一次通话后,我无法消除查看视觉效果所需的时间。这可能是最好的——即,第一次调用最多为一整秒,而同一缓冲区内的后续调用则为光速。
(defun my-modeline-face-function ()
(cond
((minibufferp)
(set 'face-remapping-alist '(
(mode-line modeline-inactive-face)
(minibuffer-prompt minibuffer-prompt-active-face))) )
(save-as-variable
(set 'face-remapping-alist '((mode-line save-as-modeline-face))))
(insert-variable
(set 'face-remapping-alist '((mode-line insert-modeline-face))))
((or multi-extract-variable multi-attach-variable)
(set 'face-remapping-alist '((mode-line multi-attach-extract-modeline-face))))
(open-with-variable
(set 'face-remapping-alist '((mode-line open-with-modeline-face))))
(mc-mode
(set 'face-remapping-alist '((mode-line mc-modeline-face))))
(isearch-mode
(set 'face-remapping-alist '((mode-line isearch-modeline-face))))
((eq major-mode 'lawlist-calculator-mode)
(set 'face-remapping-alist '((mode-line lawlist-calculator-modeline-face))))
(t
(set 'face-remapping-alist '(
(mode-line modeline-active-face)
(minibuffer-prompt minibuffer-prompt-inactive-face))) )))
【问题讨论】:
-
你对函数进行了字节编译吗?
-
@Dan -- 谢谢你的建议。我只是尝试将它从我的非字节编译库中分离出来,然后我创建了一个单独的库并对其进行了字节编译,然后 gz 压缩了 *.el 文件并重新启动了 Emacs。然而,同样的延迟仍然存在。我在想函数
set-face-attribute与'mode-line一起只是一个耗时的过程,也许它与我的自定义函数无关,这只是一些简单的条件。通常,具有几个条件的函数应该运行得比人类感知的快得多。 -
set-face-attribute会成为这样的瓶颈似乎很奇怪。在不知道*-variable子句是什么的情况下,很难猜测那里是否存在瓶颈。也许尝试分析代码(manual node、wiki page、SO thread)。 -
我可能完全错了,但我认为您可能会在重新显示期间尝试设置人脸属性来自找麻烦(如果它是模式行的一部分,大概是在调用您的函数时)格式的东西)。我怀疑在原位可能很难对此进行分析(在重新显示期间会关闭调试等功能,并且分析可能也会如此 - 不知道)。但您可以按原样分析它,而不是重新显示。这就是开始的地方,看看是你的函数运行缓慢还是因为在重新显示期间尝试执行它而导致运行缓慢。
-
@Drew -- 谢谢你的建议。为了今天进行后续测试,我从方程式中完全消除了我的自定义函数。
set-face-attribute只是在更改模式线颜色时需要很多时间。set-face-background和set-face-foreground也需要很长时间。有趣的是,face-remap-add-relative第一次被调用时花费了同样长的时间,但此后每次都以光速运行。因此,此问题的最终解决方案可能需要弄清楚为什么face-remap-add-relative在后续调用中以光速工作。