在我的Windows机器上,git stash
在每次调用时都有大约3.5秒的开销,这为我的git commit hook添加了大约7秒。
linux(同一台机器)下的相同命令大约需要0.01秒。性能问题也适用于空存储库。
我从this thread和this thread尝试了以下内容:
core.fscache
将被设置为true
core.preloadindex
将被设置为true
gc.auto
将被设置为256
运行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
运行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
从日志中我们看到运行git-stash命令和运行git-rev-parse之间需要大约3秒钟。我可以运行其他任何标志来找到瓶颈吗?
随着Git for Windows 2.19(2018年9月),git stash
(和git rebase
)不再是脚本,但实际上是用git.exe
编译的二进制文件。
见git-for-windows/build-extra PR 203。
要激活它们,请键入:
git config --global rebase.useBuiltin true
git config --global stash.useBuiltin true
警告:
和加速一样好,有问题的补丁仍在不断变化,它们根本没有经过战斗测试。
那么,就目前而言,git stash
的脚本版本仍然是默认的,这样:
- 希望通过三个并行工作的Google Summer of Code项目获得原始速度提升的用户可以拥有
- 而其他不愿意通过运行经过良好测试的代码来玩豚鼠的人可以保持安全。
重点仍然是:在Git的下一个版本中,git-stash
的bash脚本最终将消失,并且它的替换将会更快。
使用Git 2.22更新2019年第二季度,git stash
完全用C语言重写。
参见commit 40af146的commit 48ee24a,commit ef0f0b4,commit 64fe9c2,commit 1ac528c,commit d553f53,commit d4788af,commit 41e0dd5,commit dc7bd38,commit 130f269,commit bef55dc,commit dac566c,commit ab8ad46,Paul-Sebastian Ungureanu (weekly-digest[bot]
)(2019年2月25日)。
参见commit c4de61d,commit 577c199,commit 4e2dd39,commit 8a0fc8d,Joel Teichroeb (klusark
)(2019年2月25日)。
参见commit 7906af0,commit 90a4627,commit 8d8e9c2,Johannes Schindelin (dscho
)(2019年2月25日)。
(由Junio C Hamano -- gitster
--合并于commit e36adf7,2019年4月22日)
你仍然可以use the shell script with git legacy-stash
。
和:
stash
: convertstash--helper.c
intostash.c
旧的shell脚本
git-stash.sh
被删除并完全由builtin/stash.c
取代。 为了做到这一点,create
和push
适应没有stash.sh
工作。例如,在此提交之前,
git stash create
称为git stash--helper create --message "$*"
。如果它叫git stash--helper create "$@"
,那么其中一些变化就没有必要了。此提交还删除了单词
helper
,因为现在stash是直接调用而不是shell脚本。
有优化:
stash
: optimizeget_untracked_files()
andcheck_changes()
此提交通过避免再次调用相同的函数来引入优化。 例如,
git stash push -u
会在某些方面调用以下函数:
check_changes()
(在do_push_stash()
内)do_create_stash()
,称为:check_changes()
和get_untracked_files()
请注意,
check_changes()
也称get_untracked_files()
。 因此,check_changes()
被称为2次,get_untracked_files()
被称为3次。旧函数
check_changes()
现在由两个函数组成:get_untracked_files()
和check_changes_tracked_files()
。这些是
push
和create
的调用链:
push_stash()
- >do_push_stash()
- >do_create_stash()
create_stash()
- >do_create_stash()
为了防止一遍又一遍地调用相同的函数,
check_changes()
中的do_create_stash()
现在放在调用函数中(create_stash()
和do_push_stash()
)。 这样,check_changes()
和get_untracked files()
只被召唤一次。
git-stash
是一个脚本,而不是在git.exe
二进制文件中编译的命令。
在linux上:我可以在git-stash
找到/usr/lib/git-core/git-stash
- 我会让你在windows上寻找正确的路径......
这个脚本使用#!/bin/sh
来运行,我不知道在windows上运行时使用了什么shell实现。
你可以尝试用另一个兼容的shell运行它(这里: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
您还可以打开-x
标志,该标志将打印执行的所有命令的跟踪,并目视检查其中一个子命令是否似乎是挂钩:
$ PATH=/usr/lib/git-core:$PATH bash -x /usr/lib/git-core/git-stash