Magit extremadamente lento en Windows. ¿Cómo optimizo?

15

Me veo obligado a usar Windows 10 para un proyecto. Sí, prefiero usar GNU / Linux. Para mantener mi cordura, he tratado de considerar a Windows como un gestor de arranque para Emacs :)

Desafortunadamente, Magit (una de mis partes favoritas de Emacs, que también compensa la falta de una buena línea de comando en Windows) es insoportablemente lenta. Tengo una SSD, 16 GB de RAM y un i7 de cuatro núcleos, pero tarda ocho segundos en ejecutarse magit-statusen un pequeño repositorio. Luego, cuando quiero realizar otro cambio, me lleva unos 5 segundos por archivo .

Esto es lo que he intentado:

  • $ git config --global core.preloadindex true
  • $ git config --global core.fscache true
  • $ git config --global gc.auto 256
  • Agregar todo el proyecto a la lista de exclusión de Windows Defender (mi único AV)
  • Configurando el magit-git-executablemsysgit normal que descargué ( https://git-for-windows.github.io/ ). Lo comprobé y git statusaquí lleva <1 segundo. Sé que eso magit-statushace mucho más, pero esto es demasiado.

¿Alguien puede sugerir formas de hacer esto más rápido? No puedo imaginar a nadie usando Magit en Windows de esta manera.

Se sugirió que esta pregunta es un duplicado, pero preguntaron:

Me cuesta entender por qué Emacs tiene un tiempo de inicio notablemente más corto en Ubuntu que en Windows. Alguien sabe la respuesta?

Conozco al menos algunas razones por las que Emacs, Git y Magit son más lentos en Windows. Me pregunto cómo optimizo Magit para hacer menos cosas, o resultados de caché, o algo, incluso si es a expensas de la funcionalidad.

Choza8
fuente
git-statustoma <1 segundo? Debería ser esencialmente instantáneo. ¿Hay algún retraso perceptible en absoluto?
PythonNut
¿Tiene los mismos problemas al ejecutar los gitcomandos equivalentes desde la línea de comandos?
Elethan
Creo que la opción predeterminada de magit para magit-git-executableprobablemente sea un poco más rápida (las que están cmdy binson realmente envoltorios, siexecutable-find devuelve uno de ellos, magit intentará establecer magit-git-executableel git "real"). Sin embargo, 8 segundos para un repositorio pequeño parece que algo más está mal, toma ~ 0.8s para el repositorio de magit aquí (Windows 8).
npostavs
1
Además, durante un tiempo más exacto, podría establecer magit-refresh-verbosea t.
niñera

Respuestas:

11

De hecho, he investigado bastante sobre esto y, fundamentalmente, el problema es que git para Windows apesta

Este es el error ascendente: https://github.com/git-for-windows/git/issues/596 y requiere que alguien reescriba los scripts de shell en C para que no haya más bifurcación de comandos. Para mí, es el rebase interactivo el verdadero asesino (puedo comenzar un rebase interactivo, ir a preparar té, volver, leer algunas noticias, beber el té y luego tal vez esté terminado. Es mucho peor que mucha gente creo que sí), pero las llamadas de estado general también son suficientes para interrumpir el paso de trabajo.

Una alternativa podría ser actualizar jGit para admitir los comandos que usa magit, y luego ejecutarlo en nailgun para reducir el tiempo de inicio de JVM, comencé un hilo para discutir esto: http://dev.eclipse.org/mhonarc/lists/ jgit-dev / msg03064.html

Es posible que desee leer /programming/4485059 para conocer algunas posibles aceleraciones, pero, sinceramente, apenas las notará.

Algo que puede hacer en magit es seguir los consejos del autor para configurar un mínimo magit-statussolo para la puesta en escena

;; 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))

Entonces, ¿conoces a algún desarrollador experimentado de C o Java que pueda ayudar con cualquiera de las soluciones para arreglar git o jGit?

fommil
fuente
No estoy tan seguro de que el problema sean los scripts de shell vs. C, porque también magit-statuslleva mucho tiempo, y no creo que el estado use muchos de los scripts de shell.
niñera
1
Y gracias por ese magit-statuscódigo "mínimo" , parece que me ayuda un poco (reduce mi magit-refreshtiempo a 2-3 segundos).
niñera
Esto es exactamente lo que quiero. ¡Gracias!
Choza8
1
Sí, magit-stagingtoma un par de segundos para mí también. Lo suficiente como para interrumpir mi pensamiento, pero no lo suficiente como para destruir mi día.
fommil
2
La razón por la que magit-statuses lenta es porque se llama a git10 o 20 veces. Iniciar nuevos procesos en Windows es extremadamente lento en comparación con las plataformas GNU. Los scripts de shell son un caso extremo de esto (porque casi todas las declaraciones son un proceso nuevo)
fommil
2

Después de mirar recientemente una lista de call-processllamadas magit-statuspor otra razón, se me ocurrió que algunas de ellas se pueden almacenar en caché. Con los siguientes consejosmagit-status sobre el repositorio de Magit va de 1.9 a 1.3 segundos (mi medición anterior de 0.8s mencionada en los comentarios fue para una computadora diferente (más rápida)). Si ya está usando magit-stagingla otra respuesta, probablemente no sea de mucha ayuda: vi una reducción de 0.16 a 0.12 segundos (pero eso es apenas mayor que el ruido de medición).

ADVERTENCIA: Esto no se encarga de actualizar el caché, por lo que las cosas pueden salir mal (especialmente si está jugando con su configuración de 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
fuente
¿Por qué no usas el paquete melpa.org/#/memoize ?
fommil
1
@fommil: necesitaba memorizar rev-parse por buffer para algunos argumentos. No pude ver una manera de hacerlo después de una mirada superficial al paquete de memorizar. También dice que no puede manejar la memorización nil.
npostavs