我有一个小型存储库和一个大型存储库(包含许多二进制文件).
现在,当我在小型存储库中检出分支时,工作目录会立即切换到新内容.
现在在大型存储库中,它可能需要10-15秒.我的理论是,在后一种情况下,git需要时间:
>删除当前工作目录
>从内部git DB中提取新的工作目录 – 基本上意味着解压缩很多二进制文件.
但是我没有找到任何支持这个的文件?什么决定了当地的结账时间,它是否如上所述那么简单?
最佳答案
The more the number of changes, longer the
git checkout
operation takes.
是.从外部的角度来看,就这么简单.
为了更好地理解内部结构,首先看一下这个excellent answer,了解内部程序的摘要,然后是git checkout.
为了更加迂腐并开始深入挖掘,这里是一个“典型”git checkout的配置文件,涉及10,000个文件大约需要7s(在本地Linux内核git存储库中切换分支):
time strace -c git checkout master > git-checkout-strace.txt
Checking out files: 100% (10651/10651), done.
Switched to branch 'master'
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
27.21 0.067416 4 18336 write
25.83 0.063994 6 10229 7 unlink
14.88 0.036865 3 11182 1775 open
8.28 0.020507 2 12136 689 lstat
7.97 0.019744 6581 3 1 futex
5.53 0.013699 1 9409 close
5.21 0.012910 1 8913 fstat
2.96 0.007327 15 480 273 rmdir
...
...
...
(skipping the rest of long list that accounts for the remaining 1% time)
------ ----------- ----------- --------- --------- ----------------
100.00 0.247793 71970 2767 total
real 0m7.148s
user 0m2.606s
sys 0m4.137s
一些有趣的事实:
>最耗时的系统调用是open(),write()和unlink().
它们组合在一起,占系统调用时间的2/3.
>系统调用实际上只花了0.24s(总共7.14s).
>另外在strace -r下运行git checkout将显示任意2个连续系统调用之间的时间间隔.
运行strace -r git checkout master> git的结帐-strace的,intervals.txt
然后是awk'{print $1}’git-checkout-strace-relative-timestamps.txt |分类
在排序列表的末尾找到系统调用之间的大间隔.
0.000167 rename(".git/index.lock", ".git/index") = 0
0.462548 brk(0x38ac000) = 0x38ac000
上面的代码片段表明git在重命名index.lock但在决定请求更多内存(malloc() – > brk)之前,正在忙着做几乎半秒钟的事情(确切地说是0.462548s)
在典型的git checkout运行中,当git看起来在用户空间中忙而不发出任何系统调用时,你会发现六个这样的实例.记下它们以供进一步检查.
一旦你对这种理解水平感到满意,
接下来继续看看actual implementation of git checkout
.
掌握了执行过程中git在哪里停滞的知识,您可以简单地查找上面的实例周围的实现,这些实现已被记录下来以便进一步检查以了解更多关于git正在做什么的信息.