Git 将 Emacs 减慢到死亡 - 如何解决这个问题?
Posted
技术标签:
【中文标题】Git 将 Emacs 减慢到死亡 - 如何解决这个问题?【英文标题】:Git slows down Emacs to Death - How to Fix this? 【发布时间】:2011-10-07 03:46:50 【问题描述】:打开文件(通过键入Ctrl-x f
,AKA Find File
)或在Dired
模式下对该文件键入f
),在具有.git
子目录的工作目录中速度非常慢。
即使是最简单的文件(50 行,主要是 cmets)也可能需要 8 秒才能打开。
同一文件,位于不受 Git 管理的不同目录中,会立即打开。
为什么会发生这种情况,我该如何在不禁用 vc-mode 的情况下解决这个问题? (因为我使用 Emacs 的主要原因之一是它的M-x ediff-revision
)
更新 1:感谢@sanityinc 在下面的回答,我运行了 ELP 分析,这就是我收到的(对于一个非常小的文件,69 行,其中 59 行是普通 cmets):
Function Name Call Count Elapsed Time Average Time
------------- ---------- ------------ ------------
vc-call-backend 11 23.023 2.093
vc-find-file-hook 1 8.757 8.757
vc-mode-line 1 7.812 7.812
vc-default-mode-line-string 1 7.345 7.345
vc-state-refresh 1 6.921 6.921
vc-state 1 6.921 6.921
vc-default-state-heuristic 1 6.921 6.921
vc-registered 1 0.945 0.945
vc-backend 1 0.945 0.945
vc-git-registered 1 0.912 0.912
vc-working-revision 1 0.4240000000 0.4240000000
vc-find-root 4 0.0990000000 0.0247500000
vconcat 623 0.0220000000 3.53...e-005
vc-bzr-registered 1 0.016 0.016
vc-check-master-templates 2 0.014 0.007
vc-default-registered 2 0.014 0.007
vc-rcs-registered 1 0.008 0.008
vc-sccs-registered 1 0.006 0.006
vc-svn-registered 1 0.002 0.002
vc-cvs-registered 1 0.001 0.001
vc-sccs-search-project-dir 1 0.0 0.0
vc-kill-buffer-hook 6 0.0 0.0
vc-find-backend-function 11 0.0 0.0
vc-default-find-file-hook 1 0.0 0.0
vc-possible-master 6 0.0 0.0
vc-file-clearprops 1 0.0 0.0
vc-file-setprop 3 0.0 0.0
vc-file-getprop 5 0.0 0.0
vc-make-backend-sym 15 0.0 0.0
这是很好的信息,但我不是 Emacs/elisp 专家,那么我该怎么做呢?
更新 2: 将这个问题搁置了一段时间后,我发现了这篇很棒的博文:Cygwin slow start up: the culprit discovered!,它实质上建议在后台启动 bash 完成。我很快实现了它并重新运行了 ELP 分析测试:
vc-call-backend 11 14.489 1.317
vc-find-file-hook 1 5.488 5.488
vc-mode-line 1 5.118 5.118
vc-default-mode-line-string 1 4.719 4.719
vc-state-refresh 1 4.282 4.282
vc-state 1 4.282 4.282
vc-default-state-heuristic 1 4.282 4.282
vc-working-revision 1 0.437 0.437
vc-registered 1 0.37 0.37
vc-backend 1 0.37 0.37
vc-git-registered 1 0.34 0.34
vc-find-root 4 0.088 0.022
vc-bzr-registered 1 0.015 0.015
vc-check-master-templates 2 0.013 0.0065
vc-default-registered 2 0.013 0.0065
vc-rcs-registered 1 0.007 0.007
vc-sccs-registered 1 0.006 0.006
vc-cvs-registered 1 0.001 0.001
vconcat 623 0.001 1.60...e-006
vc-svn-registered 1 0.001 0.001
vc-sccs-search-project-dir 1 0.0 0.0
vc-kill-buffer-hook 6 0.0 0.0
vc-find-backend-function 11 0.0 0.0
vc-default-find-file-hook 1 0.0 0.0
vc-possible-master 6 0.0 0.0
vc-file-clearprops 1 0.0 0.0
vc-file-setprop 3 0.0 0.0
vc-file-getprop 5 0.0 0.0
vc-make-backend-sym 15 0.0 0.0
很高兴看到vc-call-backend
从 23 秒下降到 14 秒,但这仍然是不可接受的(找到 CVS 控制的文件不到一瞬间!)。
更新 3: 无法解开谜团,我通过升级到最新的 cygwin (1.7.9-1) 来试试运气。这没有帮助。
因此,我决定尝试将沙箱(连同其 .git
子目录)从 Samba 共享移动到本地存储 (C:\Users\WinWin\Documents
)。然后我重新运行了 ELP 分析测试:
vc-call-backend 11 2.082 0.1892727272
vc-find-file-hook 1 0.897 0.897
vc-git--call 7 0.8929999999 0.1275714285
vc-git-mode-line-string 1 0.78 0.78
vc-mode-line 1 0.78 0.78
vc-default-mode-line-string 1 0.655 0.655
vc-git--out-ok 5 0.6519999999 0.1304
vc-git-state 1 0.53 0.53
vc-state-refresh 1 0.53 0.53
vc-state 1 0.53 0.53
vc-default-state-heuristic 1 0.53 0.53
vc-git-working-revision 2 0.25 0.125
vc-git-registered 2 0.2239999999 0.1119999999
vc-git--run-command-string 1 0.18 0.18
vc-working-revision 1 0.125 0.125
vc-registered 1 0.1169999999 0.1169999999
vc-backend 2 0.1169999999 0.0584999999
vc-git--empty-db-p 1 0.11 0.11
vc-find-root 3 0.003 0.001
vc-git-root 2 0.002 0.001
vc-check-master-templates 2 0.001 0.0005
vc-sccs-registered 1 0.001 0.001
vc-default-registered 2 0.001 0.0005
vc-bzr-registered 1 0.001 0.001
vc-rcs-registered 1 0.0 0.0
vc-sccs-search-project-dir 1 0.0 0.0
vc-kill-buffer-hook 5 0.0 0.0
vc-default-find-file-hook 1 0.0 0.0
vc-possible-master 6 0.0 0.0
vc-cvs-registered 1 0.0 0.0
vc-file-clearprops 1 0.0 0.0
vc-file-setprop 3 0.0 0.0
vc-file-getprop 5 0.0 0.0
vc-svn-registered 1 0.0 0.0
vc-make-backend-sym 2 0.0 0.0
哇!这将vc-call-backend
从 14 秒降低到 2 秒。这很棒但并不美妙,因为使用 Emacs/CVS 我可以在 不到 35 毫秒 内访问一个文件——在沙盒最初所在的同一个 Samba 共享上:
vc-call-backend 5 0.031 0.0062
vc-find-file-hook 1 0.031 0.031
vc-registered 1 0.031 0.031
vc-backend 1 0.031 0.031
vc-rcs-registered 1 0.016 0.016
vc-check-master-templates 1 0.016 0.016
vc-default-registered 1 0.016 0.016
vc-insert-file 1 0.015 0.015
vc-cvs-get-entries 1 0.015 0.015
vc-cvs-registered 1 0.015 0.015
vc-cvs-state-heuristic 1 0.0 0.0
vc-cvs-parse-sticky-tag 1 0.0 0.0
vc-kill-buffer-hook 1 0.0 0.0
vc-find-backend-function 1 0.0 0.0
vc-cvs-parse-entry 1 0.0 0.0
vc-mode-line 1 0.0 0.0
vc-default-find-file-hook 1 0.0 0.0
vc-possible-master 3 0.0 0.0
vc-cvs-mode-line-string 1 0.0 0.0
vc-default-mode-line-string 1 0.0 0.0
vc-state-refresh 1 0.0 0.0
vc-working-revision 1 0.0 0.0
vc-state 1 0.0 0.0
vc-file-clearprops 1 0.0 0.0
vc-file-setprop 5 0.0 0.0
vc-file-getprop 7 0.0 0.0
vc-make-backend-sym 2 0.0 0.0
这提出了两个问题:
-
git+cygwin 的组合使它如此敏感
网速?
我怎样才能让 git 降到 50 毫秒以下?毕竟是调用
“快速版本控制系统”
使用 msysgit 1.7.8 时更新:
vc-call-backend 11 0.626 0.0569090909
vc-find-file-hook 1 0.281 0.281
vc-mode-line 1 0.2189999999 0.2189999999
vc-default-mode-line-string 1 0.1879999999 0.1879999999
vc-state-refresh 1 0.157 0.157
vc-state 1 0.157 0.157
vc-default-state-heuristic 1 0.157 0.157
vc-registered 1 0.062 0.062
vc-backend 1 0.062 0.062
vc-git-registered 1 0.062 0.062
vc-working-revision 1 0.0310000000 0.0310000000
vc-rcs-registered 1 0.0 0.0
vc-sccs-search-project-dir 1 0.0 0.0
vc-kill-buffer-hook 6 0.0 0.0
vc-find-backend-function 11 0.0 0.0
vc-default-find-file-hook 1 0.0 0.0
vc-possible-master 6 0.0 0.0
vc-check-master-templates 2 0.0 0.0
vc-cvs-registered 1 0.0 0.0
vc-sccs-registered 1 0.0 0.0
vc-file-clearprops 1 0.0 0.0
vconcat 623 0.0 0.0
vc-default-registered 2 0.0 0.0
vc-file-setprop 3 0.0 0.0
vc-find-root 4 0.0 0.0
vc-file-getprop 5 0.0 0.0
vc-bzr-registered 1 0.0 0.0
vc-svn-registered 1 0.0 0.0
vc-make-backend-sym 15 0.0 0.0
你能分辨出来吗? :)
Emacs 下的 Git 现在速度快了很多,但它仍然比 Emacs 下的 CVS 慢得多。所以我不知道为什么 Git 被称为“快速版本控制系统”。它可能比 CVS 更好,但更快?
【问题讨论】:
更多关于存储库状态的信息会很有用,例如a) 文件是否在 git 中注册? b) 还有其他未注册的文件吗? c) repo 中是否有文件有大量修改未决? @sanityinc (a) 是的,文件是用git注册的,比较新的文件,目前只有2次提交。 (b) 所有文件都已注册,除了一个“gitignored”子目录。 (c) repo 中的所有文件都已完全提交,没有待修改。附:它是一个四核 64 位机器,所以不应该为这件事情的缓慢找借口。 :) @sanityinc 在 Emacs 中打开该文件时,M-! git status
需要 5-6 秒。
而且大概 git 在命令行上要快得多?你是通过 Cygwin 使用 git 吗?
Windows 很奇怪。我的 bash 提示需要几秒钟才能在 cygwin 下显示,我无法确定。我想一些相关的影响是导致你的 git 调用永远需要。问题在于您的 git 二进制文件(或文件系统),而不是 Emacs。 FWIW,我在 Windows Emacs 和 Windows (msys) Git 上运气不错。为什么需要 cygwin?
【参考方案1】:
有一个名为 ELP 的内置分析器。您可以尝试类似M-x elp-instrument-package
,输入“vc”,然后尝试查找文件。之后,M-x elp-results
将向您显示个人资料报告。
(请注意,如果时间花在与 vc 无关的函数上,此技术将不会显示,但您可以根据需要检测更多包。)
【讨论】:
接受您的提示是接近解开谜团最有帮助的方法。我倾向于接受您的观察,即问题可能出在我的git
设置上,而不是 Emacs。我将尝试在一个单独的线程中解决这个问题。再次感谢。【参考方案2】:
你可以尝试profile打开你的文件,看看究竟是什么花费了这么多时间。
【讨论】:
感谢 +1 让我注意到 Emacs Native Profiler,因为我以前不知道它。不幸的是,它在底部显示“目前仅支持 Linux”,而我在 Windows 7 下使用 Emacs。【参考方案3】:我在使用 mingw emacs 25.1.1 的 windows git 2.10 时遇到了同样的问题。
使用以下测试:
(progn
;; make sure the buffer is not already open
(elp-instrument-function 'find-file-other-window)
(elp-instrument-function 'vc-git-registered)
(elp-instrument-function 'vc-git-mode-line-string)
(elp-instrument-function 'vc-git-find-file-hook)
(find-file-other-window "my-file-in-a-git-repo")
(elp-results)
(elp-restore-all))
提供以下个人资料:
find-file-other-window 1 1.1076142 1.1076142
vc-git-mode-line-string 1 0.6396082 0.6396082
vc-git-find-file-hook 1 0.2652034 0.2652034
vc-git-registered 1 0.1872024 0.1872024
vc-git-mode-line-string
函数需要一段时间。这会在窗口的模式行中显示类似 Git:mybranch
的内容。我不太在意每次都等待它,所以我覆盖实现只返回"Git"
:
(defun vc-git-mode-line-string (file)
"Overwritten default vc-git-el implementation. Return a string
for `vc-mode-line' to put in the mode line for FILE."
"Git")
vc-git-find-file-hook
函数将在您打开一个冲突文件时打开一个相当冲突的编辑模式。实现首先调用vc-git-conflicted-files
,这需要一段时间,然后做一个相当简单的检查是否有任何行以<<<<<<<
开头。我只是简单地交换了两者,现在大多数情况下实现大约需要 0.0 秒。
(defun vc-git-find-file-hook ()
"Overwritten default vc-git-el implementation. Activate
`smerge-mode' if there is a conflict."
(when (and buffer-file-name
;; FIRST check whether this file looks like a conflicted file
(save-excursion
(goto-char (point-min))
(re-search-forward "^<<<<<<< " nil 'noerror))
;; THEN ask git if it really is a conflict
(vc-git-conflicted-files buffer-file-name))
(vc-file-setprop buffer-file-name 'vc-state 'conflict)
(smerge-start-session)
(when vc-git-resolve-conflicts
(add-hook 'after-save-hook 'vc-git-resolve-when-done nil 'local))
(vc-message-unresolved-conflicts buffer-file-name)))
结果:
find-file-other-window 1 0.2838039 0.2838039
vc-git-registered 1 0.2682037 0.2682037
vc-git-find-file-hook 1 0.0 0.0
vc-git-mode-line-string 1 0.0 0.0
【讨论】:
【参考方案4】:您可以通过在.emacs
中将vc-handled-backends
设置为nil
来disable vc-mode。
【讨论】:
@robert & @Alex Ott 我使用 Emacs 的主要原因之一是ediff-revisions
。难道没有更好的方法来加快速度吗?毕竟,Emacs 不会对 CVS 版本控制下的文件这样做......以上是关于Git 将 Emacs 减慢到死亡 - 如何解决这个问题?的主要内容,如果未能解决你的问题,请参考以下文章