Magit чрезвычайно медленный в Windows. Как мне оптимизировать?

15

Я вынужден использовать Windows 10 для проекта. Да, я бы предпочел использовать GNU / Linux. Чтобы сохранить здравомыслие, я пытался рассматривать Windows как загрузчик для Emacs :)

К сожалению, Magit (одна из моих любимых частей Emacs, которая также компенсирует отсутствие хорошей командной строки в Windows) невыносимо медленна. У меня есть SSD, 16 ГБ оперативной памяти и четырехъядерный процессор i7 , но это занимает восемь секунд , чтобы выполнить magit-statusна небольшое хранилище. Затем, когда я хочу внести другое изменение, это занимает около 5 секунд на файл .

Вот что я попробовал:

  • $ git config --global core.preloadindex true
  • $ git config --global core.fscache true
  • $ git config --global gc.auto 256
  • Добавление всего проекта в список исключений Защитника Windows (мой единственный AV)
  • Установка magit-git-executableобычного msysgit, который я скачал ( https://git-for-windows.github.io/ ). Я проверил и git statusздесь занимает <1 секунды. Я знаю, что magit-statusэто намного больше, но это слишком много.

Кто-нибудь может предложить способы сделать это быстрее? Я не могу представить, чтобы кто-нибудь использовал Magit на Windows, как это.

Было высказано предположение, что этот вопрос является дубликатом, но они спросили:

Я изо всех сил пытаюсь понять, почему Emacs заметно короче время запуска в Ubuntu, чем Windows. Кто-нибудь знает ответ?

Я знаю по крайней мере несколько причин, почему Emacs, Git и Magit работают медленнее в Windows. Я спрашиваю, как я могу оптимизировать Magit, чтобы делать меньше вещей, или кэшировать результаты, или что-то еще, даже если это в ущерб функциональности.

Hut8
источник
git-statusзанимает <1 секунду? Это должно быть по существу мгновенно. Есть ли ощутимая задержка вообще?
PythonNut
Есть ли у вас такие же проблемы при запуске эквивалентных gitкоманд из командной строки?
elethan
Я думаю, что выбор magit по умолчанию magit-git-executable, вероятно, будет немного быстрее (те, которые находятся cmdи binявляются фактически обертками, если executable-findвозвращает один из них, magit попытается установить magit-git-executable«реальный» git). 8 секунд для небольшого репозитория звучат, как будто что-то еще не так, однако, для репозитория magit здесь требуется ~ 0.8с (Windows 8).
npostavs
1
Кроме того , для более точного времени, вы можете установить magit-refresh-verboseв t.
няня

Ответы:

11

Я действительно провел довольно много исследований по этому вопросу, и в основном проблема в том, что GIT для Windows отстой

Это вышестоящая ошибка: https://github.com/git-for-windows/git/issues/596, и она требует, чтобы кто-то переписал сценарии оболочки на C, чтобы больше не было разветвления команд. Для меня это интерактивная перебазировка, которая является настоящим убийцей (я могу начать интерактивную перебазировку, пойти приготовить чай, вернуться, почитать новости, выпить чай, а потом, возможно, все закончится. Это гораздо хуже, чем у многих людей. думаю, что это так), но общих вызовов, подобных статусу, также достаточно, чтобы прервать работу.

Альтернативой может быть обновление jGit для поддержки команд, которые использует magit, а затем запуск его в nailgun для сокращения времени запуска JVM. Я начал обсуждение этого: http://dev.eclipse.org/mhonarc/lists/ jgit-DEV / msg03064.html

Возможно, вы захотите прочитать /programming/4485059 для некоторых потенциальных ускорений, но, честно говоря, вы едва заметите их.

Что вы можете сделать в magit, так это следовать совету автора по настройке минимума magit-statusтолько для постановки

;; WORKAROUND https://github.com/magit/magit/issues/2395
(define-derived-mode magit-staging-mode magit-status-mode "Magit staging"
  "Mode for showing staged and unstaged changes."
  :group 'magit-status)
(defun magit-staging-refresh-buffer ()
  (magit-insert-section (status)
    (magit-insert-untracked-files)
    (magit-insert-unstaged-changes)
    (magit-insert-staged-changes)))
(defun magit-staging ()
  (interactive)
  (magit-mode-setup #'magit-staging-mode))

Итак, знаете ли вы опытных разработчиков на C или Java, которые могли бы помочь с любым из решений для исправления git или jGit?

fommil
источник
Я не уверен, что проблема в сценариях оболочки по сравнению с C, потому что это также magit-statusзанимает очень много времени, и я не думаю, что status использует многие из сценариев оболочки.
няня
1
И спасибо за этот «минимальный» magit-statusкод, он мне немного помогает (он сокращает мое magit-refreshвремя до 2-3 секунд).
няня
Это именно то, что я хочу. Благодарность!
Hut8
1
да, magit-stagingу меня тоже пара секунд. Достаточно, чтобы прервать мое мышление, но недостаточно, чтобы разрушить мой день.
Фоммил
2
Причина, по которой magit-statusэто происходит медленно, заключается в том, что он gitможет вызывать 10 или 20 раз. Запуск новых процессов в Windows происходит крайне медленно по сравнению с платформами GNU. Сценарии оболочки - крайний случай этого (потому что почти каждое утверждение - новый процесс)
fommil
2

Недавно просмотрев список call-processвызовов magit-statusпо другой причине, мне пришло в голову, что некоторые из них можно кэшировать. Со следующим советом magit-statusпо репо Magit идет от 1,9 до 1,3 секунд (мое предыдущее измерение 0,8 с, упомянутое в комментариях, было для другого (более быстрого) компьютера). Если вы уже используете magit-stagingдругой ответ, это, вероятно, не сильно поможет: я видел снижение с 0,16 до 0,12 секунды (но это чуть больше, чем шум измерения).

ВНИМАНИЕ: Это не заботится об обновлении кеша, поэтому что-то может пойти не так (особенно если вы возитесь с вашей конфигурацией git).

(defvar-local magit-git--git-dir-cache nil)
(defvar-local magit-git--toplevel-cache nil)
(defvar-local magit-git--cdup-cache nil)

(defun memoize-rev-parse (fun &rest args)
  (pcase (car args)
    ("--git-dir"
     (unless magit-git--git-dir-cache
       (setq magit-git--git-dir-cache (apply fun args)))
     magit-git--git-dir-cache)
    ("--show-toplevel"
     (unless magit-git--toplevel-cache
       (setq magit-git--toplevel-cache (apply fun args)))
     magit-git--toplevel-cache)
    ("--show-cdup"
     (let ((cdup (assoc default-directory magit-git--cdup-cache)))
       (unless cdup
         (setq cdup (cons default-directory (apply fun args)))
         (push cdup magit-git--cdup-cache))
       (cdr cdup)))
    (_ (apply fun args))))

(advice-add 'magit-rev-parse-safe :around #'memoize-rev-parse)

(defvar-local magit-git--config-cache (make-hash-table :test 'equal))

(defun memoize-git-config (fun &rest keys)
  (let ((val (gethash keys magit-git--config-cache :nil)))
    (when (eq val :nil)
      (setq val (puthash keys (apply fun keys) magit-git--config-cache)))
    val))

(advice-add 'magit-get :around #'memoize-git-config)
(advice-add 'magit-get-boolean :around #'memoize-git-config)
npostavs
источник
почему бы вам просто не использовать пакет melpa.org/#/memoize ?
Fommil
1
@fommil: мне нужно было запомнить rev-parse для буфера для некоторых аргументов. Я не мог найти способ сделать это после беглого взгляда на пакет memoize. Также он говорит, что не может справиться с запоминанием nil.
npostavs