Git замедляет Emacs to Death - как это исправить?
Открытие файла (либо введя Ctrl-x f
АКА Find File
) или набрав f
в этом файле в Dired
режим), мучительно медленно в рабочих каталогах, которые имеют .git
подкаталог.
Даже самый простой файл (50 строк с в основном комментариями) может открыть до 8 секунд.
Тот же файл в другом каталоге, не управляемом Git, сразу открывается.
Почему это происходит и как я могу это исправить, не отключая vc-режим? (поскольку одной из основных причин, по которой я использую Emacs, является его M-x ediff-revision
)
ОБНОВЛЕНИЕ 1: Благодаря ответу @sanityinc ниже, я запустил ELP Profiling, и вот что я получил (для очень маленького файла, 69 строк, 59 из которых - простые комментарии):
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 медленно запускается: преступник обнаружен! что, по сути, предполагает начало завершения 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
Это поднимает 2 вопроса:
- Что в сочетании с 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
Можете ли вы сказать разницу?:)
Git под Emacs теперь намного быстрее, но все еще намного медленнее, чем CVS под Emacs. Так что я понятия не имею, почему Git называется "Система быстрого контроля версий". Может быть лучше, чем CVS, но быстрее?
4 ответа
Есть встроенный профилировщик, который называется ELP. Вы можете попробовать что-то вроде M-x elp-instrument-package
введите "vc", а затем попробуйте найти файл. После этого, M-x elp-results
покажет вам профиль отчета.
(Обратите внимание, что если вместо этого время тратится на функции, не связанные с vc, этот метод не будет показывать его, но вы можете использовать дополнительные пакеты, если хотите.)
Вы можете попытаться профилировать открытие вашего файла, чтобы увидеть, что именно занимает столько времени.
Вы можете отключить vc-режим, установив vc-handled-backends
в nil
в вашем .emacs
,
У меня была такая же проблема с использованием Windows Git 2.10 из Mingw Emacs 25.1.1.
Используя следующее для тестирования:
(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