repo init --reference 如何真正帮助减少构建空间



我们正在开发Android-S,看到每个CI用户在执行"repo init"和存储库同步"操作时在本地FS上使用近385 GB的空间。 我们希望优化存储和网络速度,根据手册页,我们观察到这可以使用 --reference 命令来实现。

根据文档:


-reference 选项可用于指向具有 --mirror 同步内容的目录。这将使工作目录在从服务器获取时尽可能多地使用本地引用目录中的数据。这将通过减少网络上的数据流量使同步速度更快。

<小时 />

第一个克隆:

我们按照步骤创建了第一个参考副本,发现初始占用空间接近 385 GB。

用户-1 第一个用户现在执行了存储库初始化和存储库同步,我们看到此活动的总时间仅为 23 分钟,但它也大大减小了大小到 63 GB。

用户-2 第二个用户现在执行了存储库初始化和存储库同步,我们看到此活动的总时间仅为 23 分钟,并且还将大小减小到 63 GB。

我确实看到了网络性能的提高,但想知道实际大小如何从 385 GB 移动到 63 GB,以及 63 GB 中实际存在的内容以及参考选项 WRT 减少空间背后的真正概念是什么。

使用的命令:


export Mirror="/data/Android-s">

repo init -u ssh://$US...@android1.test.com:29418/android/manifest -b tmainline -m t-r-mainline.xml --repo-url=ssh://android1.test.com:29418/android1/repo --repo-branch=test-stable --no-repo-verify --reference=$Mirror


围绕它的任何线索或文档都非常有助于空间的处理方式,以及这是否也可能导致构建过程中的任何问题以及在此命令操作期间要采取的任何预防措施。

谢谢 阿尼什

repo sync大致相当于git fetch && git checkout

首先,它获取清单中指定的revision(如果是 ref)或upstream(如果revision是 sha1 值)。ref 引用提交,提交链接到其父提交,并递归直到根提交。每个提交都引用一个树对象。树对象引用其他树、blob 和提交。所有这些 git 对象和引用都是 git 元数据。它们被打包并从远程存储库传输。其中,斑点占用的空间最多。过渡需要一段时间。

然后,在所有存储库完成获取必要的数据后,将签出指定的revision(如果是 sha1 值)或revision的头部(如果是 ref)。结帐需要一段时间。

为了减少时间,我们可以 1) 提高网络性能;2)提高I/O性能;3) 减小获取的数据大小。在大多数情况下,我们对第 1 和第 2 项无能为力。至于第三个,repo为我们提供了一些选择。

repo init -g <groups>指示repo仅下载-g指定的存储库。有时我们不需要所有的存储库。

repo sync -c指示repo仅下载revsisionupstream指定的当前引用。如果存储库具有许多并行分支或标记,则-c有助于减少大量数据。-c标志可以通过清单中的sync-c指定。

repo init --depth=<n>指示repo执行浅层克隆/获取。它只获取 n 个深度的提交,从而减少相关对象的数量。可以通过清单中的clone-depth来指定深度。请注意,在revision是sha1值而upstreambranch的情况下,当revision不在分支头的n深度内时,浅层克隆/获取可能会失败。

--reference相比,以上都只是微不足道的技能。为了减小获取的数据大小,一个想法是尽可能排除不必要的数据,就像上述选项所做的那样,另一个想法是尽可能重用获取的数据。这就是--reference所做的。为了排除不必要的数据,我们必须仔细思考并决定哪些数据是不必要的,这是相当疲惫的。重用现有数据要舒服得多。

镜像是一组可从本地磁盘访问的现有存储库。他们拥有很多数据,其中一些是未来repo sync所必需的,而另一些则不是,但我们不在乎。为了与镜像的引用同步,git fetch重用现有数据,服务器仅打包并发送镜像中不存在的缺失对象和引用。总的来说,镜像保存的数据越多,repo sync获取的数据就越少。

在开发中,我们可能有多个用户使用不同的用户名登录到同一台计算机,并且可能会有多个计算机供更多用户使用。我们可以将镜像装载到所有这些计算机,以便所有用户(包括 CI/CD 机器人用户)都可以使用它。

我们需要考虑 I/O 性能来决定应该创建多少个镜像以及一个镜像应该有多少个存储库。备份镜像是必需的。如果镜像损坏,所有相关的存储库工作区都将被禁用。我们可以定期更新镜像,以便它们始终保存尽可能多的新数据。镜像还可以用作某些查询服务的数据源,例如获取提交更改文件的 API。

Git(也是存储库工具)足够聪明,可以只获取它需要的缺失数据。如果它在镜像中找到一些数据,它不会要求服务器重新打包并重新发送冗余数据。因此,如果不能,它将要求服务器打包并发送丢失的数据。

假设我们要同步 4 个相同的存储库工作区,A、B、C 和 D。如果我们不使用参考镜像,则占用的存储大小为 480G。

A git metadata 100G + A checkout 20G
B git metadata 100G + B checkout 20G
C git metadata 100G + C checkout 20G
D git metadata 100G + D checkout 20G

4个数据的内容是相同的。如果我们只保留其中一个并与其他 3 个共享,我们可以节省 300G。这就是--reference所做的.在--reference=/path/to/mirror的帮助下,尺寸缩小了很多。为了演示它,我们假设镜像有点小,只有 80G 的元数据。每个工作区都需要获取丢失的 20G 数据并自行存储。现在尺寸变小了80G * 3,从480G下降到240G。

Mirror 80G + A git metadata 20G + A checkout 20G
+ B git metadata 20G + B checkout 20G
+ C git metadata 20G + C checkout 20G
+ D git metadata 20G + D checkout 20G

随着获取的数据变得更小(工作区为 80G),时间成本也降低了,元数据和签出的存储成本也降低了。由于每个结帐都有自己的目的,并且它们需要同时存在,因此我们很难降低它们的成本。但是对于他们的某些存储库,我们可能会使用 LFS 或稀疏结帐来进一步优化他们的成本。

如果我们先更新镜像,镜像现在拥有所有必要的数据。我们可以节省更多。总尺寸进一步缩小到只有180G。

Mirror 100G + A git metadata 0G + A checkout 20G
+ B git metadata 0G + B checkout 20G
+ C git metadata 0G + C checkout 20G
+ D git metadata 0G + D checkout 20G

存储库的数量及其在镜像中的数据大小可能因需求而异。我们总能找到一个平衡点。在 AOSP 开发中,我们可能有不同的工作区,这些工作区由不同的存储库组成。工作区 A 具有存储库 P1、P2、P3。B 有 P2、P3、P4。C 有 P1、P2、P3、P4。D 有 P3、P4、P5。可以将镜像定义为 P1、P2、P3、P4、P5,或者只是 P2、P3、P4 或其他集合。

如果我们选择 P1、P2、P3、P4 和 P5 的集合,则样本镜像大小可能大于 100GB。但与节省的存储和时间成本相比,它仍然具有成本效益。最坏的情况是,您只有一个工作区,无论是否使用参考镜像,其成本几乎相同。通常,在参考镜像的帮助下,工作区越多,节省的成本就越多。

最新更新