Git slows down Emacs to Death - How to Fix this?
There's a built-in profiler called ELP. You can try something like M-x elp-instrument-package
, enter "vc", and then try finding a file. Afterwards, M-x elp-results
will show you a profile report.
(Note that if the time is instead being spent in non-vc-related functions, this technique will not show it, but you can instrument further packages if you like.)
I had the same problem with using windows git 2.10 from mingw emacs 25.1.1.
Using the following to test:
(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))
Gave the following profile:
find-file-other-window 1 1.1076142 1.1076142vc-git-mode-line-string 1 0.6396082 0.6396082vc-git-find-file-hook 1 0.2652034 0.2652034vc-git-registered 1 0.1872024 0.1872024
The vc-git-mode-line-string
function takes a while. This shows something like Git:mybranch
in the mode line of your window. I don't care enough about that to wait for it every time, so I overwrite the implementation to just return "Git"
:
(defun vc-git-mode-line-string (file) "Overwritten default vc-git-el implementation. Return a stringfor `vc-mode-line' to put in the mode line for FILE." "Git")
The vc-git-find-file-hook
function will open a pretty conflict editing mode if you're opening a conflicted file. The implementation was first calling vc-git-conflicted-files
which takes a while, and then doing a rather trivial check whether any lines start with <<<<<<<
. I simply swapped the two, and now the implementation takes about 0.0 seconds in most cases.
(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)))
Results:
find-file-other-window 1 0.2838039 0.2838039vc-git-registered 1 0.2682037 0.2682037vc-git-find-file-hook 1 0.0 0.0vc-git-mode-line-string 1 0.0 0.0