git stash在windows上很慢

问题描述 投票:49回答:2

在我的Windows机器上,git stash在每次调用时都有大约3.5秒的开销,这为我的git commit hook添加了大约7秒。

linux(同一台机器)下的相同命令大约需要0.01秒。性能问题也适用于空存储库。

我从this threadthis thread尝试了以下内容:

  • core.fscache将被设置为true
  • core.preloadindex将被设置为true
  • gc.auto将被设置为256
  • 设置PS1 ='$'
  • 以管理员模式运行cmd
  • 在cmd.exe中运行而不是git-bash

运行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秒钟。我可以运行其他任何标志来找到瓶颈吗?

windows git git-bash git-stash
2个回答
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更新2019年第二季度,git stash完全用C语言重写。

参见commit 40af146commit 48ee24acommit ef0f0b4commit 64fe9c2commit 1ac528ccommit d553f53commit d4788afcommit 41e0dd5commit dc7bd38commit 130f269commit bef55dccommit dac566ccommit ab8ad46Paul-Sebastian Ungureanu (weekly-digest[bot])(2019年2月25日)。 参见commit c4de61dcommit 577c199commit 4e2dd39commit 8a0fc8dJoel Teichroeb (klusark)(2019年2月25日)。 参见commit 7906af0commit 90a4627commit 8d8e9c2Johannes Schindelin (dscho)(2019年2月25日)。 (由Junio C Hamano -- gitster --合并于commit e36adf7,2019年4月22日)

你仍然可以use the shell script with git legacy-stash

和:

stash: convert stash--helper.c into stash.c

旧的shell脚本git-stash.sh被删除并完全由builtin/stash.c取代。 为了做到这一点,createpush适应没有stash.sh工作。

例如,在此提交之前,git stash create称为git stash--helper create --message "$*"。如果它叫git stash--helper create "$@",那么其中一些变化就没有必要了。

此提交还删除了单词helper,因为现在stash是直接调用而不是shell脚本。

有优化:

stash: optimize get_untracked_files() and check_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()

这些是pushcreate的调用链:

  • 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()只被召唤一次。


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
© www.soinside.com 2019 - 2024. All rights reserved.