通过快速网络连接克隆git存储库的最快方法是什么?

Tho*_*sen 23 git performance vmware git-clone

我有一个相对较大的git存储库的情况,位于我的本地网络上的老人,慢主机上,这需要很长时间才能进行初始克隆.

ravn@bamboo:~/git$ git clone gitosis@gitbox:git00
Initialized empty Git repository in /home/ravn/git/git00/.git/
remote: Counting objects: 89973, done.
remote: Compressing objects: 100% (26745/26745), done.
remote: Total 89973 (delta 50970), reused 85013 (delta 47798)
Receiving objects: 100% (89973/89973), 349.86 MiB | 2.25 MiB/s, done.
Resolving deltas: 100% (50970/50970), done.
Checking out files: 100% (11722/11722), done.
ravn@bamboo:~/git$
Run Code Online (Sandbox Code Playgroud)

gitosis中没有git特定的配置变化.

有没有办法加快接收位到网络的能力?


编辑:我需要新的存储库与上游存储库正确连接.根据我的理解,这需要git来进行克隆,因此git之外的原始位复制将不起作用.

seh*_*ehe 28

PS.公平警告:

git通常被认为是非常快.你应该尝试克隆来自darcs,bazaar,hg的完整回购(上帝保佑:TFS或颠覆......).另外,如果你经常从头开始克隆完整的回购,你无论如何都会做错事.您可以随时git remote update获得增量变化.

对于保持完全回购同步的各种其他方式,请参阅,例如

(包含其他相关SO帖子的链接)

愚蠢的副本

如前所述,您可以使用'dumb'文件传输复制存储库.

这肯定不会浪费时间压缩,重新包装,分层和/或过滤.

另外,你会得到

这可能是您需要的,也可能不是,但要注意这一事实是很好的


默认情况下,Git克隆优化带宽.由于git clone默认情况下不会镜像所有分支(请参阅参考资料--mirror),因此按原样转储pack-files是没有意义的(因为这可能会发送超过所需的数量).

在分发给真正大量的客户端时,请考虑使用捆绑包.

如果你想要一个没有服务器端成本的快速克隆,那么git方式就是bundle create.您现在可以分发捆绑包,甚至不涉及服务器.如果您的意思bundle... --all不仅仅包括简单git clone,请考虑bundle ... master减少音量.

git bundle create snapshot.bundle --all # (or mention specific ref names instead of --all)
Run Code Online (Sandbox Code Playgroud)

而是分发快照包.这是两个世界中最好的,当然你不会从上面的项目符号列表中获得这些项目.在接收端,只是

git clone snapshot.bundle myclonedir/
Run Code Online (Sandbox Code Playgroud)

压缩配置

您可以通过减少/删除压缩来降低服务器负载.看看这些配置设置(我假设pack.compression可以帮助您降低服务器负载)

core.compression

整数-1..9,表示默认压缩级别.-1是zlib的默认值.0表示没有压缩,1..9是各种速度/大小权衡,9表示最慢.如果设置,则为其他压缩变量提供默认值,例如core.loosecompression和pack.compression.

core.loosecompression

整数-1..9,表示不在包文件中的对象的压缩级别.-1是zlib的默认值.0表示没有压缩,1..9是各种速度/大小权衡,9表示最慢.如果未设置,则默认为core.compression.如果未设置,则默认为1(最佳速度).

pack.compression

整数-1..9,表示包文件中对象的压缩级别.-1是zlib的默认值.0表示没有压缩,1..9是各种速度/大小权衡,9表示最慢.如果未设置,则默认为core.compression.如果未设置,则默认为-1,即zlib默认值,即"速度和压缩之间的默认折衷(当前等效于级别6)".

请注意,更改压缩级别不会自动重新压缩所有现有对象.您可以通过将-F选项传递给git-repack(1)来强制重新压缩.

鉴于充裕的网络带宽,这在事实上导致更快的克隆.不要忘记git-repack -F何时决定对此进行基准测试!

  • 你问了一个问题,然后你有可能得到答案._如果你能接受你得到的答案你不希望它会很好_(你可以梦想选择`git clone`,但不存在它们不是我的错).我用更多背景信息更新了我的答案 (4认同)
  • “(上帝保佑:TFS 或颠覆……)”让我笑了。美好的过去。 (2认同)

nor*_*ree 25

使用深度创建浅克隆.

git clone --depth 1 <repository>
Run Code Online (Sandbox Code Playgroud)


Von*_*onC 6

git clone --depth=1 ... 2014 年建议将在 2019 年第二季度使用 Git 2.22 变得更快。
这是因为,在初始的“ git clone --depth=...”部分克隆期间,为枚举和跳过承诺对象(根据定义是从另一侧获取的所有对象)的大部分连接检查花费周期是毫无意义的。
这已经被优化了。

clone:对部分克隆进行更快的对象检查

对于部分克隆,进行完整的连接检查是浪费;我们跳过promisor对象(对于部分克隆,它是所有已知对象),并枚举它们以将它们从连接检查中排除在大型存储库中可能需要大量时间。

最多,我们想确保我们得到任何想要的引用所引用的对象。
对于部分克隆,只需检查这些对象是否已传输。

结果:

 Test                          dfa33a2^         dfa33a2
 -------------------------------------------------------------------------
 5600.2: clone without blobs   18.41(22.72+1.09)   6.83(11.65+0.50) -62.9%
 5600.3: checkout of result    1.82(3.24+0.26)     1.84(3.24+0.26) +1.1%
Run Code Online (Sandbox Code Playgroud)

速度提高 62%!


在 Git 2.26(2020 年第 1 季度)中,现在在获取部分克隆时禁用了不需要的连接检查。

请参阅Jonathan Tan ( ) 的commit 2df1aa2commit 5003377(2020 年 1 月 12 日(由Junio C Hamano合并-- --提交 8fb3945 中,2020 年 2 月 14 日)jhowtan
gitster

connected: 验证部分克隆的承诺

签字人:Jonathan Tan
审核人:Jonathan Nieder

提交dfa33a298d(“ clone:对部分克隆进行更快的对象检查”,2019-04-21,Git v2.22.0-rc0 -- merge)优化了在克隆时完成的连接检查,--filter以仅检查 refs 直接指向的对象的存在.
但这还不够:它们还需要是承诺对象。
通过检查这些对象是否是承诺对象,即它们出现在承诺包中,使此检查更加健壮。

和:

fetch:放弃完全连接检查是否 --filter

签字人:Jonathan Tan
审核人:Jonathan Nieder

如果指定了过滤器,我们不需要对刚刚获取的包文件的内容进行完整的连接检查;我们只需要检查引用的对象是否是承诺对象。

这显着加快了对具有许多承诺对象的存储库的提取速度,因为在连接检查期间,所有承诺对象都被枚举(以将它们标记为不感兴趣),这需要大量时间。


而且,在 Git 2.26(2020 年第一季度)中,对象可达性位图机制和部分克隆机制还没有准备好协同工作,因为部分克隆使用的某些对象过滤标准本质上依赖于对象遍历,但位图机制是绕过该对象遍历的优化

然而,在某些情况下,他们可以一起工作,并且他们被教导了这些。

请参阅Junio C Hamano () 的commit 20a5fd8(2020 年 2 月 18 日。 见提交3ab3185提交84243da提交4f3bd56提交cc4aa28提交2aaeb9a提交6663ae0提交4eb707e提交ea047a8提交608d9c9提交55cb10f提交792f811提交d90fe06(2020年2月14日),以及提交e03f928提交acac50d提交551cf8b(2020 年 2 月 13 日)作者:Jeff King ( )gitster
peff.
(由Junio C gitsterHamano合并-- --0df82d9 提交中,2020 年 3 月 2 日)

pack-bitmap: 实现BLOB_LIMIT过滤

签字人:Jeff King

就像之前实现BLOB_NONE提交一样,我们可以BLOB_LIMIT通过查看结果中任何 blob 的大小并适当地取消设置它们的位来支持过滤器。
这比略贵,BLOB_NONE,但仍然产生明显的加速(这些结果在git.git 上):

Test                                         HEAD~2            HEAD
------------------------------------------------------------------------------------
5310.9:  rev-list count with blob:none       1.80(1.77+0.02)   0.22(0.20+0.02) -87.8%
5310.10: rev-list count with blob:limit=1k   1.99(1.96+0.03)   0.29(0.25+0.03) -85.4%
Run Code Online (Sandbox Code Playgroud)

实现与实现类似,不同之处BLOB_NONE在于我们必须在遍历 blob 类型位图时逐个对象(因为我们无法屏蔽匹配项,但必须单独查找每个 blob 的大小) .
using 的技巧ctz64()来自show_objects_for_type(),它同样需要找到单个位(但想要快速跳过没有 blob 的大块)。


Git 2.27(2020 年第 2 季度)将简化部分克隆存储库中的提交祖先连接性检查,其中假定“承诺”对象可以从承诺远程存储库按需延迟获取。

请参阅Jonathan Tan ( ) 的commit 2b98478 (20 Mar 2020 )(由Junio C Hamano合并-- --commit 0c60105,2020 年 4 月 22 日)jhowtan
gitster

connected: 始终使用部分克隆优化

签字人:Jonathan Tan
评论人:Josh Steadmon

使用50033772d5(“ connected:验证部分克隆的承诺”,2020 年 1 月 30 日,Git v2.26.0-rc0 --合并第 5 批中列出),快速路径(检查承诺包)check_connected()现在通过慢路径(rev-list)> - 如果在promisor包中找到所有要检查的对象,则快路径和慢路径都将通过;

  • 否则,快速路径肯定不会通过。

这意味着每当我们需要做慢速路径时,我们总是可以尝试快速路径。

快速路径目前由标志保护;因此,删除该标志。
此外,让快速路径回退到慢速路径——如果快速路径失败,失败的 OID 和所有剩余的 OID 将传递给 rev-list。

主要的用户可见的好处是从部分克隆中获取的性能 - 特别是在获取之前完成的连接检查的加速。
特别是,对我计算机上部分克隆的无操作提取从 7 秒加快到 0.01 秒。这是对2df1aa239c 中工作的补充(“ fetchforgo full connections check if --filter”, 2020-01-30, Git v2.26.0-rc0 -- merge列在第 5 批中),它是前面提到的50033772d5。在该提交中,提取的连接检查加速。

在这些情况下,添加快速路径可能会导致性能下降:

  • 如果部分克隆或获取部分克隆失败,Git 将毫无结果地运行rev-list(预计获取的所有内容都将进入承诺包,因此如果没有发生,则 rev-list 很可能也会失败) .

  • 在(在我看来,不太可能)部分克隆服务于接收包的情况下,接收包完成的任何连接检查。

我认为这些情况很少见,而且这种情况下的性能下降足够小(额外的对象数据库访问),避免标志的好处超过了这些。


在 Git 2.27(2020 年第二季度)中,带有对象过滤器“ --filter=tree:0”的对象遍历现在可以在可用时利用包位图。

请参阅Jeff King ( ) 的commit 9639474commit 5bf7f1e(2020 年 5 月 4 日。 请参阅Taylor Blau ( ) 的提交 b0a8d48856e12c (2020 年 5 月 4 日)(由Junio C Hamano合并-- --提交 69ae8ff 中,2020 年 5 月 13 日)peff
ttaylorr
gitster

pack-bitmap.c: 支持 'tree:0' 过滤

签字人:Taylor Blau

在上一个补丁中,我们可以轻松定义排除某种类型的所有对象的其他过滤器。--filter=tree:<n>当“ n”等于时,使用它来为“ ”过滤器实现位图级过滤0

位图对一般情况没有帮助,因为对于 ' n > 0' 的值,对象过滤机制需要完整的树遍历以确定给定树的深度。
缓存这也是不明显的,因为相同的树对象可以根据上下文具有不同的深度(例如,树在两次提交之间的目录层次结构中向上移动)。

但是,“ n = 0” 情况可以提供帮助,而这个补丁就是这样做的。在这棵树上
运行p5310.11,并在带有内核的 master 上运行,我们可以看到这种情况有很大帮助:

Test                                  master              this tree
--------------------------------------------------------------------------------
5310.11: rev-list count with tree:0   10.68(10.39+0.27)   0.06(0.04+0.01) -99.4%
Run Code Online (Sandbox Code Playgroud)

和:

请参阅Jeff King ( ) 的commit 9639474commit 5bf7f1e(2020 年 5 月 4 日。 请参阅Taylor Blau ( ) 的提交 b0a8d48856e12c (2020 年 5 月 4 日)(由Junio C Hamano合并-- --提交 69ae8ff 中,2020 年 5 月 13 日)peff
ttaylorr
gitster

pack-bitmap: 通过对象过滤器进行填充遍历

签字人:Jeff King
签字人:Taylor Blau

有时位图遍历仍然需要手动遍历一些提交,因为这些提交不包含在位图打包文件中(例如,由于自上次完全重新打包以来的推送或提交)。

如果我们得到一个对象过滤器,我们不会将它传递给这个遍历。
正确性不是必需的,因为位图代码有自己的过滤器来对位图结果进行后处理(它必须过滤掉位图包文件提到的对象)。

对于 blob 过滤器,也没有传递这些过滤器的性能原因。填充遍历可以从结果中省略它们,但它不会为我们节省任何时间,因为我们仍然必须遍历每个树条目以查看它是否是 blob。

但既然我们支持树过滤器,就有机会节省成本。一个tree:depth=0过滤装置,我们可以完全避免访问树,因为我们知道,我们不会把他们(或子树或斑点它们指向的)。
中的新测试p5310显示了这一点(“部分位图”状态是一种HEAD~100及其祖先都在位图包中的状态,但HEAD~100..HEAD不是)。

以下是结果(针对linux.git):

Test                                                  HEAD^               HEAD
-------------------------------------------------------------------------------------------------
[...]
5310.16: rev-list with tree filter (partial bitmap)   0.19(0.17+0.02)     0.03(0.02+0.01) -84.2%
Run Code Online (Sandbox Code Playgroud)

储蓄的绝对数量并不庞大,但请记住,我们只省略100第一父链接(在版本的linux.git在这里,这是894个实际提交)。

在更病态的情况下,我们可能有更大比例的非位图提交。我没有费心在 perf 脚本中创建这样的案例,因为设置很昂贵,这足以显示节省的百分比。


在 Git 2.32(2021 年第二季


Tho*_*sen 4

在意识到数据传输速度的上限是在git“外部”建立的ssh连接之后,我做了一些实验,发现使用pcsp(Putty scp)的上限是3,0 MB/s因为河豚加密方案选择得当。使用raw ftp进行控制实验表明传输速度为3.1 MB/s,因此表明这是网络的上限。

它在 vmware hypervisor 内运行,并且由于执行网络 I/O 的进程几乎使用了 100% cpu,因此表明瓶颈是 Ubuntu 网卡驱动程序。然后我发现,即使安装了 vmware 工具,由于某种原因,内核仍然使用 vlance 驱动程序(模拟具有 IRQ 等的 10 MBps 网卡)而不是 vmxnet 驱动程序(直接与虚拟机管理程序对话)。现在等待服务窗口进行更改。

换句话说,问题不在于git,而在于底层的“硬件”。