git stash is slow on windows

2019-01-31 05:57发布

问题:

On my windows machine git stash has about 3.5 seconds overhead on each invocation, which adds about 7 seconds to my git commit hook.

The same command under linux (same machine) takes about 0.01 seconds. The performance issue applies to empty repositories as well.

I have tried the following from this thread and this thread:

  • core.fscache is set to true
  • core.preloadindex is set to true
  • gc.auto is set to 256
  • Setting PS1='$ '
  • Running cmd in administration mode
  • Running inside cmd.exe instead of git-bash

Running GIT_TRACE=true git stash list

16:58:16.844591 git.c:563               trace: exec: 'git-stash' 'list'
16:58:16.844591 run-command.c:336       trace: run_command: 'git-stash' 'list'
16:58:19.699591 git.c:350               trace: built-in: git 'rev-parse' '--git-dir'
16:58:19.859591 git.c:350               trace: built-in: git 'rev-parse' '--git-path' 'objects'
16:58:20.069591 git.c:350               trace: built-in: git 'rev-parse' '--show-toplevel'
16:58:20.154591 git.c:350               trace: built-in: git 'rev-parse' '--git-path' 'index'
16:58:20.244591 git.c:350               trace: built-in: git 'config' '--get-colorbool' 'color.interactive'
16:58:20.334591 git.c:350               trace: built-in: git 'config' '--get-color' 'color.interactive.help' 'red bold'
16:58:20.424591 git.c:350               trace: built-in: git 'config' '--get-color' '' 'reset'
16:58:20.514591 git.c:350               trace: built-in: git 'rev-parse' '--verify' '--quiet' 'refs/stash'

real    0m3.845s
user    0m0.000s
sys     0m0.047s

Running GIT_TRACE_PERFORMANCE=true git stash list

16:59:18.414591 trace.c:420             performance: 0.001078046 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-dir'                                          
16:59:18.569591 trace.c:420             performance: 0.000947184 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-path' 'objects'                               
16:59:18.779591 trace.c:420             performance: 0.001253627 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--show-toplevel'                                    
16:59:18.869591 trace.c:420             performance: 0.001285517 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-path' 'index'                                 
16:59:18.955591 trace.c:420             performance: 0.001139994 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-colorbool' 'color.interactive'                   
16:59:19.040591 trace.c:420             performance: 0.001182881 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-color' 'color.interactive.help' 'red bold'       
16:59:19.125591 trace.c:420             performance: 0.001128997 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-color' '' 'reset'                                
16:59:19.215591 trace.c:420             performance: 0.001567766 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--verify' '--quiet' 'refs/stash'                    
16:59:19.295591 trace.c:420             performance: 3.730583540 s: git command: 'C:\Program Files\Git\mingw64\bin\git.exe' 'stash' 'list'                                                                

real    0m3.819s                                                                                                                                                                                          
user    0m0.000s                                                                                                                                                                                          
sys     0m0.062s                                                                                                                                                                                          

From the log we see that it takes around 3 seconds between the git-stash command is run and the git-rev-parse is run. Are there any other flags I can run to find the bottleneck?

回答1:

With Git for Windows 2.19 (Sept. 2018), git stash (and git rebase) are no longer script-only, but actually a binary compiled with git.exe.
See git-for-windows/build-extra PR 203.

To activate them, type:

git config --global rebase.useBuiltin true
git config --global stash.useBuiltin true

Warning:

As nice as the speed-ups are, the patches in question are still in flux, and they are not battle-tested at all.

So, for now, the script version of git stash remains the default, that way:

  • users who want the raw speed improvement we got through three Google Summer of Code projects working in parallel can have that,
  • while others who are reluctant to play guinea pig by running only well-tested code can stay on the safe side.

The point remains: in the next versions of Git, the bash script for git-stash will eventually disappear, and its replacement is and will be faster.



回答2:

git-stash is a script, not a command compiled in the git.exe binary.

On linux : I can find git-stash at /usr/lib/git-core/git-stash - I will let you look for the correct path on windows ...


This script uses #!/bin/sh to run, I don't know what shell implementation is used when you run this on windows.

You can try to run it with another compatible shell (here: bash) :

# the git-core/ dir needs to be in the PATH,
# obviously  you will need to provide the correct path for your git-core dir

$ PATH=/usr/lib/git-core:$PATH bash /usr/lib/git-core/git-stash

You can also turn the -x flag, which will print a trace of all commands executed, and visually check if one of the sub commands seems to be the hanger :

$ PATH=/usr/lib/git-core:$PATH bash -x /usr/lib/git-core/git-stash