Git rallenta Emacs to Death – Come risolvere il problema?

Aprire un file (digitando Ctrl-x f Dired , AKA Find File ) o digitando f in quel file in modalità Dired ), è dolorosamente lento nelle directory di lavoro che hanno una sottodirectory .git .

Anche il file più semplice (50 righe con commenti per lo più) potrebbe richiedere fino a 8 secondi per l’apertura.

Lo stesso file, in una diversa directory non gestita da Git, si apre immediatamente, immediatamente.

Perché sta accadendo questo e come posso risolvere questo problema senza disabilitare la modalità vc? (dal momento che uno dei motivi principali per cui utilizzo Emacs è la sua Mx ediff-revision )

AGGIORNAMENTO 1: Grazie alla risposta di @ sanityinc di seguito, ho eseguito ELP Profiling e questo è ciò che ho ricevuto (per un file molto piccolo, 69 righe, di cui 59 semplici commenti):

 Function Name Call Count Elapsed Time Average Time ------------- ---------- ------------ ------------ vc-call-backend 11 23.023 2.093 vc-find-file-hook 1 8.757 8.757 vc-mode-line 1 7.812 7.812 vc-default-mode-line-string 1 7.345 7.345 vc-state-refresh 1 6.921 6.921 vc-state 1 6.921 6.921 vc-default-state-heuristic 1 6.921 6.921 vc-registered 1 0.945 0.945 vc-backend 1 0.945 0.945 vc-git-registered 1 0.912 0.912 vc-working-revision 1 0.4240000000 0.4240000000 vc-find-root 4 0.0990000000 0.0247500000 vconcat 623 0.0220000000 3.53...e-005 vc-bzr-registered 1 0.016 0.016 vc-check-master-templates 2 0.014 0.007 vc-default-registered 2 0.014 0.007 vc-rcs-registered 1 0.008 0.008 vc-sccs-registered 1 0.006 0.006 vc-svn-registered 1 0.002 0.002 vc-cvs-registered 1 0.001 0.001 vc-sccs-search-project-dir 1 0.0 0.0 vc-kill-buffer-hook 6 0.0 0.0 vc-find-backend-function 11 0.0 0.0 vc-default-find-file-hook 1 0.0 0.0 vc-possible-master 6 0.0 0.0 vc-file-clearprops 1 0.0 0.0 vc-file-setprop 3 0.0 0.0 vc-file-getprop 5 0.0 0.0 vc-make-backend-sym 15 0.0 0.0 

Questa è un’ottima informazione, ma io non sono un esperto di Emacs / Elisp, quindi come posso andare da qui?

AGGIORNAMENTO 2: Dopo aver inserito questo problema nel dimenticatoio per un po ‘, mi sono imbattuto in questo fantastico post sul blog: Cygwin ha avviato lentamente: il colpevole scoperto! che essenzialmente suggerisce di iniziare il completamento di bash in background. L’ho implementato rapidamente e ho eseguito nuovamente il test di profiling ELP:

 vc-call-backend 11 14.489 1.317 vc-find-file-hook 1 5.488 5.488 vc-mode-line 1 5.118 5.118 vc-default-mode-line-string 1 4.719 4.719 vc-state-refresh 1 4.282 4.282 vc-state 1 4.282 4.282 vc-default-state-heuristic 1 4.282 4.282 vc-working-revision 1 0.437 0.437 vc-registered 1 0.37 0.37 vc-backend 1 0.37 0.37 vc-git-registered 1 0.34 0.34 vc-find-root 4 0.088 0.022 vc-bzr-registered 1 0.015 0.015 vc-check-master-templates 2 0.013 0.0065 vc-default-registered 2 0.013 0.0065 vc-rcs-registered 1 0.007 0.007 vc-sccs-registered 1 0.006 0.006 vc-cvs-registered 1 0.001 0.001 vconcat 623 0.001 1.60...e-006 vc-svn-registered 1 0.001 0.001 vc-sccs-search-project-dir 1 0.0 0.0 vc-kill-buffer-hook 6 0.0 0.0 vc-find-backend-function 11 0.0 0.0 vc-default-find-file-hook 1 0.0 0.0 vc-possible-master 6 0.0 0.0 vc-file-clearprops 1 0.0 0.0 vc-file-setprop 3 0.0 0.0 vc-file-getprop 5 0.0 0.0 vc-make-backend-sym 15 0.0 0.0 

È bello vedere il vc-call-backend scendere da 23 secondi a 14 secondi, ma questo è ancora inaccettabile (trovare un file controllato dal CVS richiede meno di un secondo!).

AGGIORNAMENTO 3: Incapace di risolvere il mistero, ho tentato la fortuna aggiornando all’ultimo cygwin (1.7.9-1). Questo non ha aiutato.

Così, ho deciso di provare a spostare la sandbox (insieme alla sua sottodirectory .git ) dalla condivisione Samba alla memoria locale ( C:\Users\WinWin\Documents ). Ho quindi rieseguito il test di profiling ELP:

 vc-call-backend 11 2.082 0.1892727272 vc-find-file-hook 1 0.897 0.897 vc-git--call 7 0.8929999999 0.1275714285 vc-git-mode-line-string 1 0.78 0.78 vc-mode-line 1 0.78 0.78 vc-default-mode-line-string 1 0.655 0.655 vc-git--out-ok 5 0.6519999999 0.1304 vc-git-state 1 0.53 0.53 vc-state-refresh 1 0.53 0.53 vc-state 1 0.53 0.53 vc-default-state-heuristic 1 0.53 0.53 vc-git-working-revision 2 0.25 0.125 vc-git-registered 2 0.2239999999 0.1119999999 vc-git--run-command-string 1 0.18 0.18 vc-working-revision 1 0.125 0.125 vc-registered 1 0.1169999999 0.1169999999 vc-backend 2 0.1169999999 0.0584999999 vc-git--empty-db-p 1 0.11 0.11 vc-find-root 3 0.003 0.001 vc-git-root 2 0.002 0.001 vc-check-master-templates 2 0.001 0.0005 vc-sccs-registered 1 0.001 0.001 vc-default-registered 2 0.001 0.0005 vc-bzr-registered 1 0.001 0.001 vc-rcs-registered 1 0.0 0.0 vc-sccs-search-project-dir 1 0.0 0.0 vc-kill-buffer-hook 5 0.0 0.0 vc-default-find-file-hook 1 0.0 0.0 vc-possible-master 6 0.0 0.0 vc-cvs-registered 1 0.0 0.0 vc-file-clearprops 1 0.0 0.0 vc-file-setprop 3 0.0 0.0 vc-file-getprop 5 0.0 0.0 vc-svn-registered 1 0.0 0.0 vc-make-backend-sym 2 0.0 0.0 

Wow! Ciò ha ridotto il vc-call-backend da 14 secondi a 2 secondi. Questo è ottimo ma non eccezionale, perché con Emacs / CVS posso visitare un file in meno di 35 ms – sulla stessa condivisione Samba in cui risiede originariamente la sandbox:

 vc-call-backend 5 0.031 0.0062 vc-find-file-hook 1 0.031 0.031 vc-registered 1 0.031 0.031 vc-backend 1 0.031 0.031 vc-rcs-registered 1 0.016 0.016 vc-check-master-templates 1 0.016 0.016 vc-default-registered 1 0.016 0.016 vc-insert-file 1 0.015 0.015 vc-cvs-get-entries 1 0.015 0.015 vc-cvs-registered 1 0.015 0.015 vc-cvs-state-heuristic 1 0.0 0.0 vc-cvs-parse-sticky-tag 1 0.0 0.0 vc-kill-buffer-hook 1 0.0 0.0 vc-find-backend-function 1 0.0 0.0 vc-cvs-parse-entry 1 0.0 0.0 vc-mode-line 1 0.0 0.0 vc-default-find-file-hook 1 0.0 0.0 vc-possible-master 3 0.0 0.0 vc-cvs-mode-line-string 1 0.0 0.0 vc-default-mode-line-string 1 0.0 0.0 vc-state-refresh 1 0.0 0.0 vc-working-revision 1 0.0 0.0 vc-state 1 0.0 0.0 vc-file-clearprops 1 0.0 0.0 vc-file-setprop 5 0.0 0.0 vc-file-getprop 7 0.0 0.0 vc-make-backend-sym 2 0.0 0.0 

Questo solleva 2 domande:

  1. Che cosa nella combinazione di git + cygwin rende così sensibile alla velocità della rete?
  2. Come posso far scendere git a meno di 50ms? Dopo tutto, è chiamata “il sistema di controllo della versione veloce

Aggiornamento quando si utilizza msysgit 1.7.8:

 vc-call-backend 11 0.626 0.0569090909 vc-find-file-hook 1 0.281 0.281 vc-mode-line 1 0.2189999999 0.2189999999 vc-default-mode-line-string 1 0.1879999999 0.1879999999 vc-state-refresh 1 0.157 0.157 vc-state 1 0.157 0.157 vc-default-state-heuristic 1 0.157 0.157 vc-registered 1 0.062 0.062 vc-backend 1 0.062 0.062 vc-git-registered 1 0.062 0.062 vc-working-revision 1 0.0310000000 0.0310000000 vc-rcs-registered 1 0.0 0.0 vc-sccs-search-project-dir 1 0.0 0.0 vc-kill-buffer-hook 6 0.0 0.0 vc-find-backend-function 11 0.0 0.0 vc-default-find-file-hook 1 0.0 0.0 vc-possible-master 6 0.0 0.0 vc-check-master-templates 2 0.0 0.0 vc-cvs-registered 1 0.0 0.0 vc-sccs-registered 1 0.0 0.0 vc-file-clearprops 1 0.0 0.0 vconcat 623 0.0 0.0 vc-default-registered 2 0.0 0.0 vc-file-setprop 3 0.0 0.0 vc-find-root 4 0.0 0.0 vc-file-getprop 5 0.0 0.0 vc-bzr-registered 1 0.0 0.0 vc-svn-registered 1 0.0 0.0 vc-make-backend-sym 15 0.0 0.0 

Puoi dire la differenza? 🙂

Git sotto Emacs è molto più veloce ora, ma è ancora molto più lento di CVS in Emacs. Quindi non ho idea del perché Git sia chiamato “Fast Version Control System”. Potrebbe essere migliore di CVS, ma più veloce?

C’è un profiler incorporato chiamato ELP. Puoi provare qualcosa come Mx elp-instrument-package , inserire “vc”, e quindi provare a trovare un file. Successivamente, Mx elp-results ti mostreranno un rapporto profilo.

(Si noti che se si impiega il tempo in funzioni non correlate a vc, questa tecnica non lo mostrerà, ma se lo si desidera è ansible strumentare ulteriori pacchetti).

Puoi provare a profilare l’apertura del tuo file per vedere esattamente cosa ci vuole così tanto tempo.

Puoi disabilitare la modalità vc-handled-backends impostando i vc-handled-backends da vc-handled-backends nil nel tuo .emacs .

Ho avuto lo stesso problema con l’utilizzo di Windows Git 2.10 da Mingw Emacs 25.1.1.

Usando quanto segue per testare:

 (progn ;; make sure the buffer is not already open (elp-instrument-function 'find-file-other-window) (elp-instrument-function 'vc-git-registered) (elp-instrument-function 'vc-git-mode-line-string) (elp-instrument-function 'vc-git-find-file-hook) (find-file-other-window "my-file-in-a-git-repo") (elp-results) (elp-restore-all)) 

Ha dato il seguente profilo:

 find-file-other-window 1 1.1076142 1.1076142 vc-git-mode-line-string 1 0.6396082 0.6396082 vc-git-find-file-hook 1 0.2652034 0.2652034 vc-git-registered 1 0.1872024 0.1872024 

La funzione vc-git-mode-line-string richiede un po ‘di tempo. Questo mostra qualcosa come Git:mybranch nella riga della modalità della finestra. Non mi interessa abbastanza per aspettarlo ogni volta, quindi sovrascrivo l’implementazione per restituire semplicemente "Git" :

 (defun vc-git-mode-line-string (file) "Overwritten default vc-git-el implementation. Return a string for `vc-mode-line' to put in the mode line for FILE." "Git") 

La funzione vc-git-find-file-hook aprirà una bella modalità di modifica dei conflitti se stai aprendo un file in conflitto. L’implementazione è stata inizialmente chiamata vc-git-conflicted-files che richiede un po ‘di tempo, e quindi fa un controllo piuttosto banale se le linee iniziano con <<<<<<< . Ho semplicemente scambiato i due, e ora l'implementazione richiede circa 0,0 secondi nella maggior parte dei casi.

 (defun vc-git-find-file-hook () "Overwritten default vc-git-el implementation. Activate `smerge-mode' if there is a conflict." (when (and buffer-file-name ;; FIRST check whether this file looks like a conflicted file (save-excursion (goto-char (point-min)) (re-search-forward "^<<<<<<< " nil 'noerror)) ;; THEN ask git if it really is a conflict (vc-git-conflicted-files buffer-file-name)) (vc-file-setprop buffer-file-name 'vc-state 'conflict) (smerge-start-session) (when vc-git-resolve-conflicts (add-hook 'after-save-hook 'vc-git-resolve-when-done nil 'local)) (vc-message-unresolved-conflicts buffer-file-name))) 

risultati:

 find-file-other-window 1 0.2838039 0.2838039 vc-git-registered 1 0.2682037 0.2682037 vc-git-find-file-hook 1 0.0 0.0 vc-git-mode-line-string 1 0.0 0.0