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.