37

Opening a file (either by typing Ctrl-x f, AKA Find File) or by typing f on that file in Dired mode), is painfully slow in working directories that have a .git subdirectory.

Even the simplest file (50 lines with mostly comments) could take up to 8 seconds to open.

The same file, in a different directory not managed by Git, opens in a jiffy, immediately.

Why is this happening and how can I fix this without disabling vc-mode? (since one of the main reasons I use Emacs is its M-x ediff-revision)

UPDATE 1: Thanks to @sanityinc's answer below, I ran ELP Profiling and this is what I received (for a very small file, 69 lines, 59 of which are plain comments):

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 

This is great information but I am not an Emacs/elisp expert, so how where do I go from here?

UPDATE 2: After putting this problem on the back burner for a while, I came across this great blog post: Cygwin slow start up: the culprit discovered! which essentially suggests starting bash completion in the background. I quickly implemented it and re-ran the ELP profiling test:

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 

It's great to see vc-call-backend going down from 23 seconds to 14 seconds, but this is still unacceptable (finding a CVS-controlled file takes less than a split-second!).

UPDATE 3: Unable to solve the mystery, I tried my luck by upgrading to the latest cygwin (1.7.9-1). That didn't help.

So, I decided to try moving the sandbox (along with its .git subdirectory) from the Samba share to local storage (C:\Users\WinWin\Documents). I then re-ran the ELP profiling test:

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! That lowered vc-call-backend from 14 seconds to 2 seconds. This is great but not wonderful, because with Emacs/CVS I am able to visit a file in less than 35ms -- on the same Samba share where the sandbox originally resides:

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 

This raises 2 questions:

  1. What in the combination of git+cygwin makes it so sensitive to network speed?
  2. How can I make git go down to less than 50ms? After all, it is call "the fast version control system"

Update when using 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 

Can you tell the difference? :)

Git under Emacs is way faster now, but it still much much slower than CVS under Emacs. So I have no idea why Git is called the "Fast Version Control System". It may be better than CVS, but faster?

12
  • 1
    More info about the state of the repository would be useful, e.g. a) Is the file registered with git? b) are there other unregistered files? c) Are there files in the repo which have large modifications pending? Commented Jul 18, 2011 at 21:45
  • @sanityinc (a) Yes, the file is registered with git, relatively new file, only 2 commits so far. (b) All files are registered, except for one "gitignored" subdirectory. (c) All files in the repo are fully committed, no modifications pending. P.S. It's a quad-core 64-bit machine, so there should be no excuses for the slowness of this thing. :) Commented Jul 18, 2011 at 21:54
  • 1
    @sanityinc It takes 5-6 seconds to M-! git status while that file is open in Emacs. Commented Jul 19, 2011 at 19:13
  • 1
    And presumably git is much faster on the command line? Are you using git via Cygwin? Commented Jul 21, 2011 at 8:04
  • 2
    Windows is weird. My bash prompt takes a few seconds to display under cygwin for no reason I can determine. I imagine some related effect is causing your git invocations to take forever. The problem is with your git binary (or filesystem), not with Emacs. FWIW, I've had fine luck with Windows Emacs and Windows (msys) Git. Why do you need cygwin? Commented Dec 5, 2011 at 3:42

4 Answers 4

43

There's a built-in profiler called ELP. You can try something like M-x elp-instrument-package, enter "vc", and then try finding a file. Afterwards, M-x elp-results will show you a profile report.

(Note that if the time is instead being spent in non-vc-related functions, this technique will not show it, but you can instrument further packages if you like.)

Sign up to request clarification or add additional context in comments.

1 Comment

Accepting as your tip was the most helpful one to getting close to solving the mystery. I tend to accept your observation that the problem may lie in my git setup, not Emacs. I will try to address this in a separate thread. Thank again.
4

You can try to profile the opening of your file to see exactly what takes so much time.

1 Comment

Thanks +1 for bringing the Emacs Native Profiler to my attention as I didn't know about it before. Unfortunately, at the bottom it says "Currently, only Linux is supported" and I am using Emacs under Windows 7.
3

You can disable vc-mode by setting vc-handled-backends to nil in your .emacs.

1 Comment

@robert & @Alex Ott One of the main reasons I use Emacs is ediff-revisions. Isn't there a better way to speed up things? After all, Emacs doesn't do that with files under CVS version control...
3

I had the same problem with using windows git 2.10 from mingw emacs 25.1.1.

Using the following to test:

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

Gave the following profile:

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 

The vc-git-mode-line-string function takes a while. This shows something like Git:mybranch in the mode line of your window. I don't care enough about that to wait for it every time, so I overwrite the implementation to just return "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") 

The vc-git-find-file-hook function will open a pretty conflict editing mode if you're opening a conflicted file. The implementation was first calling vc-git-conflicted-files which takes a while, and then doing a rather trivial check whether any lines start with <<<<<<<. I simply swapped the two, and now the implementation takes about 0.0 seconds in most cases.

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

Results:

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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.