我有一个小型存储库和一个大型存储库(包含大量二进制文件)。
现在,当我在小型存储库中签出分支时,工作目录会立即切换到新内容。
现在在大型存储库中,它可能需要10-15秒。我的理论是,在后一种情况下,git需要时间:
但是我还没有找到任何支持此文件的文件?什么决定了当地的结账时间,它是否如上所述那么简单?
答案 0 :(得分:2)
更改次数越多,
git checkout
操作的时间就越长。
是。从外部角度来看, IS 就这么简单。
为了更好地了解内部情况,请先查看此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)。
同时在git checkout
下运行strace -r
将显示任意两次连续系统调用之间的时间间隔。
运行strace -r git checkout master > git-checkout-strace-intervals.txt
然后是awk '{print $1}' git-checkout-strace-relative-timestamps.txt | sort
在排序列表的末尾找到系统调用之间的大间隔。
0.000167 rename(".git/index.lock", ".git/index") = 0
0.462548 brk(0x38ac000) = 0x38ac000
上面的代码片段表明git在重命名index.lock
之后但在决定请求更多内存(malloc()
- >之前,正忙着做了近半秒钟(准确地说是0.462548秒) ; brk
)
在典型的git checkout
运行中,当git看起来在用户空间中忙而不发出任何系统调用时,您会发现六个这样的实例。 记下它们以供进一步检查。
一旦你对这种理解水平感到满意,
接下来继续查看 actual implementation of git checkout
。
了解git在执行期间确切停滞的位置,你可以简单地查找上面实例的实现,记下来进行进一步检查以了解更多关于git正在做什么。