Magit estremamente lento in Windows. Come ottimizzo?


15

Sono costretto a usare Windows 10 per un progetto. Sì, preferirei usare GNU / Linux. Per mantenere la sanità mentale, ho provato a considerare Windows come un bootloader per Emacs :)

Sfortunatamente, Magit (una delle mie parti preferite di Emacs, che compensa anche la mancanza di una buona riga di comando su Windows) è insopportabilmente lento. Ho un SSD, 16 GB di RAM e un quad-core i7 ma ci vogliono otto secondi per essere eseguito magit-statussu un piccolo repository. Quindi, quando voglio mettere in scena un'altra modifica, ci vogliono circa 5 secondi per file .

Ecco cosa ho provato:

  • $ git config --global core.preloadindex true
  • $ git config --global core.fscache true
  • $ git config --global gc.auto 256
  • Aggiunta dell'intero progetto all'elenco di esclusione di Windows Defender (il mio unico AV)
  • Impostando il magit-git-executablenormale msysgit che ho scaricato ( https://git-for-windows.github.io/ ). Ho controllato e git statusqui ci vuole <1 secondo. So che magit-statusfa molto di più, ma è troppo.

Qualcuno può suggerire modi per renderlo più veloce? Non riesco a immaginare nessuno che usi Magit su Windows in questo modo.

È stato suggerito che questa domanda è un duplicato, ma hanno chiesto:

Faccio fatica a capire perché Emacs ha notevolmente più brevi tempi di avvio su Ubuntu rispetto a Windows. Qualcuno conosce la risposta?

Conosco almeno alcuni motivi per cui Emacs, Git e Magit sono più lenti su Windows. Sto chiedendo come ottimizzare Magit per fare meno cose, risultati nella cache o qualcosa del genere, anche se è a scapito della funzionalità.


git-statusimpiega <1 secondo? Dovrebbe essere essenzialmente istantaneo. C'è qualche ritardo percettibile?
PythonNut,

Hai gli stessi problemi nell'esecuzione dei gitcomandi equivalenti dalla riga di comando?
elethan,

Penso che la scelta di default di magit magit-git-executablesarà probabilmente un po 'più veloce (quelli dentro cmde in binrealtà sono wrapper, se executable-findrestituisce uno di essi magit tenterà di impostare magit-git-executableil git "reale"). 8 secondi per un piccolo repository suona come se ci fosse qualcos'altro che non va, ma impiega ~ 0.8s per il repository di Magit qui (Windows 8).
npostavs,


1
Inoltre, per un tempo più preciso, è possibile impostare magit-refresh-verbosesu t.
tata

Risposte:


11

In realtà ho fatto molte ricerche su questo e fondamentalmente il problema è che Git per Windows fa schifo

Questo è il bug a monte: https://github.com/git-for-windows/git/issues/596 e richiede che qualcuno riscriva gli script della shell in C in modo che non ci siano più comandi di fork. Per me, è il rebase interattivo che è il vero killer (posso dare il via a un rebase interattivo, andare a fare il tè, tornare, leggere alcune notizie, bere il tè e poi forse è finito. È molto peggio di molte persone penso che lo sia), ma sono sufficienti anche chiamate di tipo generale per interrompere il passo di lavoro.

Un'alternativa potrebbe essere aggiornare jGit per supportare i comandi utilizzati da Magit e quindi eseguirlo in nailgun per ridurre il tempo di avvio di JVM, ho iniziato un thread per discutere di questo: http://dev.eclipse.org/mhonarc/lists/ jgit-dev / msg03064.html

Potresti voler leggere /programming/4485059 per alcuni potenziali accelerazioni, ma onestamente te ne accorgerai a malapena.

Qualcosa che puoi fare in magit è seguire i consigli dell'autore nell'impostare un minimal magit-statussolo per la messa in scena

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

quindi, conosci qualche sviluppatore C o Java esperto che sarebbe in grado di aiutarti con una delle soluzioni per correggere git o jGit?


Non sono così sicuro che il problema sia rappresentato dagli script di shell rispetto a C, perché magit-statusrichiede molto tempo e non credo che lo stato utilizzi molti degli script di shell.
tata

1
E grazie per quel magit-statuscodice "minimo" , mi sembra di aiutarmi un po '(riduce il mio magit-refreshtempo a 2-3 secondi).
tata

Questo è esattamente quello che voglio. Grazie!
Capanna 8

1
Sì, ci magit-stagingvogliono un paio di secondi anche per me. Abbastanza per interrompere il mio pensiero, ma non abbastanza per distruggere la mia giornata.
fommil

2
il motivo per cui magit-statusè lento è perché chiama gitforse 10 o 20 volte. L'avvio di nuovi processi su Windows è estremamente lento rispetto alle piattaforme GNU. Gli script di shell sono un caso estremo di questo (perché praticamente ogni affermazione è un nuovo processo)
fommil

2

Avendo esaminato di recente un elenco di call-processchiamate da magit-statusun altro motivo, mi è venuto in mente che alcune di esse possono essere memorizzate nella cache. Con i seguenti consigli magit-statussul repository Magit va da 1,9 a 1,3 secondi (la mia misurazione precedente di 0,8 citata nei commenti era per un computer diverso (più veloce)). Se stai già utilizzando magit-stagingl'altra risposta, probabilmente non sarà di grande aiuto: ho visto una riduzione da 0,16 a 0,12 secondi (ma questo è appena più grande del rumore di misurazione).

ATTENZIONE: Questo non si occupa di aggiornare la cache, quindi le cose potrebbero andare storte (specialmente se stai armeggiando con la tua configurazione 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)

perché non usi semplicemente il pacchetto melpa.org/#/memoize ?
fommil

1
@fommil: per alcuni argomenti ho dovuto memorizzare mem-parse per buffer . Non riuscivo a vedere un modo per farlo dopo una rapida occhiata al pacchetto memoize. Inoltre dice che non è in grado di gestire la memorizzazione di memo nil.
npostavs,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.