Magit extrêmement lent sous Windows. Comment optimiser?

15

Je suis obligé d'utiliser Windows 10 pour un projet. Oui, je préfère utiliser GNU / Linux. Pour garder ma raison, j'ai essayé de considérer Windows comme un chargeur de démarrage pour Emacs :)

Malheureusement, Magit (l'une de mes parties préférées d'Emacs, qui compense également l'absence d'une bonne ligne de commande sous Windows) est insupportablement lente. J'ai un SSD, 16 Go de RAM et un i7 quad-core mais cela prend huit secondes pour s'exécuter magit-statussur un petit référentiel. Ensuite, lorsque je souhaite effectuer un autre changement, cela prend environ 5 secondes par fichier .

Voici ce que j'ai essayé:

  • $ git config --global core.preloadindex true
  • $ git config --global core.fscache true
  • $ git config --global gc.auto 256
  • Ajout de l'ensemble du projet à la liste d'exclusion de Windows Defender (mon seul AV)
  • Définir le magit-git-executablemsysgit normal que j'ai téléchargé ( https://git-for-windows.github.io/ ). J'ai vérifié et git statusici prend <1 seconde. Je sais que cela magit-statusfait beaucoup plus, mais c'est trop.

Quelqu'un peut-il suggérer des moyens d'accélérer cela? Je ne peux pas imaginer que quelqu'un utilise Magit sur Windows comme ça.

Il a été suggéré que cette question était en double, mais ils ont demandé:

J'ai du mal à comprendre pourquoi Emacs a un temps de démarrage sensiblement plus court sur Ubuntu que sur Windows. Quelqu'un connaît la réponse?

Je connais au moins quelques raisons pour lesquelles Emacs, Git et Magit sont plus lents sous Windows. Je demande comment optimiser Magit pour faire moins de choses, ou mettre en cache les résultats, ou quelque chose, même si c'est au détriment des fonctionnalités.

Hut8
la source
git-statusprend <1 seconde? Elle doit être essentiellement instantanée. Y a-t-il un retard perceptible?
PythonNut
Avez-vous les mêmes problèmes lors de l'exécution des gitcommandes équivalentes à partir de la ligne de commande?
elethan
Je pense que le choix par défaut de magit magit-git-executablesera probablement un peu plus rapide (ceux dans cmdet binsont en fait des wrappers, si executable-findretourne l'un d'eux magit tentera de définir magit-git-executablele "vrai" git). 8 secondes pour un petit référentiel semble cependant que quelque chose d'autre ne va pas, prend environ 0,8 seconde pour le dépôt de magit ici (Windows 8).
npostavs
1
De plus, pour un temps plus précis, vous pouvez définir magit-refresh-verboseà t.
nounou

Réponses:

11

J'ai en fait fait beaucoup de recherches à ce sujet et, fondamentalement, le problème est que Git pour Windows est nul

Il s'agit du bogue en amont: https://github.com/git-for-windows/git/issues/596 et il nécessite que quelqu'un réécrive les scripts shell en C afin qu'il n'y ait plus de fourche de commande. Pour moi, c'est le rebase interactif qui est le vrai tueur (je peux lancer un rebase interactif, aller faire du thé, revenir, lire des nouvelles, boire du thé, et puis peut-être que c'est fini. C'est bien pire que beaucoup de gens pense que c'est le cas), mais les appels généraux de type statut sont également suffisants pour interrompre le rythme de travail.

Une alternative pourrait être de mettre à jour jGit pour prendre en charge les commandes que magit utilise, puis de l'exécuter dans nailgun pour réduire le temps de démarrage de la JVM, j'ai commencé un fil pour en discuter: http://dev.eclipse.org/mhonarc/lists/ jgit-dev / msg03064.html

Vous voudrez peut-être lire /programming/4485059 pour quelques accélérations potentielles, mais honnêtement, vous les remarquerez à peine.

Quelque chose que vous pouvez faire dans magit est de suivre les conseils de l'auteur pour mettre en place un minimum magit-statusjuste pour la mise en scène

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

Alors, connaissez-vous des développeurs C ou Java expérimentés qui seraient en mesure d'aider avec l'une des solutions pour corriger git ou jGit?

fommil
la source
Je ne suis pas sûr que le problème soit les scripts shell vs C, car cela magit-statusprend aussi très longtemps, et je ne pense pas que le statut utilise la plupart des scripts shell.
nounou
1
Et merci pour ce magit-statuscode "minimal" , il semble m'aider un peu (ça réduit mon magit-refreshtemps à 2-3 secondes).
nounou
C'est exactement ce que je veux. Merci!
Hut8
1
yup, magit-stagingprend quelques secondes pour moi aussi. Assez pour interrompre ma réflexion, mais pas assez pour détruire ma journée.
fommil
2
la raison pour laquelle magit-statusest lent, c'est parce qu'il appelle gitpeut-être 10 ou 20 fois. Le démarrage de nouveaux processus sur Windows est extrêmement lent par rapport aux plates-formes GNU. Les scripts shell en sont un cas extrême (car à peu près chaque instruction est un nouveau processus)
fommil
2

Ayant récemment regardé la liste des call-processappels de magit-statuspour une autre raison, il m'est apparu que certains d'entre eux peuvent être mis en cache. Avec les conseils suivants, magit-statusle dépôt de Magit passe de 1,9 à 1,3 seconde (ma mesure précédente de 0,8 s mentionnée dans les commentaires était pour un ordinateur différent (plus rapide)). Si vous utilisez déjà magit-stagingl'autre réponse, cela n'aidera probablement pas beaucoup: j'ai vu une réduction de 0,16 à 0,12 seconde (mais c'est à peine plus grand que le bruit de mesure).

AVERTISSEMENT: cela ne prend pas en charge la mise à jour du cache, donc les choses peuvent mal tourner (surtout si vous tripotez votre configuration 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
la source
pourquoi ne pas simplement utiliser le paquet melpa.org/#/memoize ?
fommil
1
@fommil: J'avais besoin de mémoriser rev-parse par tampon pour certains arguments. Je ne pouvais pas voir un moyen de le faire après un examen rapide du paquet memoize. Il indique également qu'il ne peut pas gérer la mémorisation nil.
npostavs du