在我的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秒钟。我可以运行其他任何标志来找到瓶颈吗?
答案 0 :(得分:21)
在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更新了Q2 2019,git stash
完全用C重写。
请参见commit 40af146,commit 48ee24a,commit ef0f0b4,commit 64fe9c2,commit 1ac528c,commit d553f53,commit d4788af,{{3} },commit 41e0dd5,commit dc7bd38,commit 130f269,commit bef55dc,commit dac566c(2019年2月25日)由commit ab8ad46撰写。
请参见Paul-Sebastian Ungureanu (weekly-digest[bot]
)的commit c4de61d,commit 577c199,commit 4e2dd39,commit 8a0fc8d(2019年2月25日)。
请参见Joel Teichroeb (klusark
)的commit 7906af0,commit 90a4627,commit 8d8e9c2(2019年2月25日)。
(由Johannes Schindelin (dscho
)在Junio C Hamano -- gitster
--中合并,2019年4月22日)
您仍然可以commit e36adf7。
并且:
use the shell script with
git legacy-stash
旧的外壳程序脚本
git-stash.sh
已删除,并完全由builtin/stash.c
取代。
为了做到这一点,create
和push
可以在没有stash.sh
的情况下工作。例如,在此提交之前,
git stash create
被称为git stash--helper create --message "$*"
。如果它叫git stash--helper create "$@"
,则 其中某些更改是不必要的。此提交也删除了
helper
一词,因为现在隐藏 直接调用而不是由Shell脚本调用。
有一些优化:
stash
: convertstash--helper.c
intostash.c
此提交通过避免调用 同样的功能。
例如,git stash push -u
会在某些时候调用以下函数:
check_changes()
(在do_push_stash()
内部)do_create_stash()
,它调用:check_changes()
和get_untracked_files()
请注意,
check_changes()
也会调用get_untracked_files()
。
因此,check_changes()
被调用了两次,而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()
被称为 只有一次。
答案 1 :(得分:3)
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