写点什么

将 50 万个文件放在一个 Git 存储库中,我们做了这些

  • 2022-08-11
    北京
  • 本文字数:2376 字

    阅读完需:约 8 分钟

将 50 万个文件放在一个Git存储库中,我们做了这些

本文最初发布于 Canva 工程博客。

 

在 Canva,我们有意采用了 monorepo 模式,它有好处也有坏处。自 2012 年第一次提交以来,库的规模和流量都与产品一起迅速增长。在过去的 10 年里,代码库已经从几千行增长到 2022 年的将近 6000 万行。数百名工程师在 50 万个文件中工作,每周会产生近百万行的修改(包括生成的文件),数万个提交,数千个拉动请求的合并。



从 2012 年到 2022 年 10 年间代码量的增长

 

这种增长显著降低了本地 Git 的性能,因为像git status这样的命令运行时间越来越长。在新克隆的一个 monorepo 上,git status平均需要 10 秒,而git fetch可能需要 15 秒到 1 分钟,这取决于工程师合并了多少变更。由于 Git 在工程师的工作流程中非常重要,每天多次运行这些命令会缩短工程师每天的总生产时间。而且,时间太长的话,工程师可能会进行上下文切换,这进一步降低了他们的生产率。

现有解决方案


所幸,并不是只有我们在使用 monorepo 时遇到了这个问题。GithubDropbox之前的工作以及 Git 近期的改进提供了大量可以用来提高 Git 性能的资源。多年来,多位工程师发表了数篇关于如何“让 Git 更快”的内部博文。这些工作最终形成了一个自动化脚本,建议工程师们将这个脚本作为入职培训流程的一部分。

 

首先,为了减少 Git 查找变更的开销,我们在 Watchman 中使用了fsmonitor钩子,这样就能在变更发生时捕获它们,而不是在每次运行命令时扫描存储库中的所有文件。我们还启用了feature.manyFiles,而它在后台启用了untracked cache,可以跳过没有变化的目录和文件。

 

Git 还内置了一个命令(maintenance),用来优化存储库的数据,加速其他命令的执行并减少磁盘占用。它默认是不启用的,所以我们将它注册为每日调度和每小时调度。

 

我们的 monorepo 有什么独特之处?

 

深入研究 monorepo 中的文件类型,我们发现.xlf 文件几乎占文件总数的 70%。这些.xlf文件包含针对每种语言环境翻译好的字符串。即使它们位于一个 monorepo 中,工程师也从来不会手工编辑,因为它们是在字符串翻译时自动生成的。也就是说,Git 在花费资源跟踪工程师永远不会修改的文件。然而,我们不能直接删除或忽略这些文件,因为翻译系统有它们才能顺利运行。次优解决方案是告诉 Git 不要使用稀疏签出(sparse checkout)在工作树中填充它们,局部性地忽略它们,同时仍然通过 monorepo 的其他源头跟踪它们的变化。实际上,为了使构建系统的其他部分可以正常工作,我们必须包含用于 en-AU 语言环境的字符串,但这点差异可以忽略不计。尽管忽略了这些翻译,但我们的本地环境仍然默认使用en-psaccent伪本地化语言环境运行,因此,工程师仍然要注意本地化需求。

 

我们用一个单独克隆的 monorepo 做了以下实验,使用 Git 的默认设置,没做前面提到的优化。

 


对于稀疏签出功能的使用,我们可以更进一步。通常,我们的工程师团队都是小团队,只会用到 monorepo 的一个更小的子集。例如,处理编辑器的前端工程师不太可能修改与搜索或计费服务相关的代码。如果一名工程师能告诉我们他们通常在做什么,我们就可以设计一个包含所有必需依赖项的签出模式,让他们可以在本地运行和测试代码,同时保持签出尽可能小。

 

Canva 的 monorepo 使用Bazel作为构建系统,我们在其中定义构建目标(主页、搜索服务器、导出按钮等)和它们的依赖项。也就是说,给 Bazel 定一个目标,我们就可以准确地确定哪些文件需要构建、运行和测试,并通过查询 Bazel 依赖关系图排除其他文件。在实践中,这需要更多的启发式逻辑,因为不是所有的东西都连接到了 Bazel 构建图中,需要解析符号链接,但这都是些可以解决的边缘情况。下表展示了一些示例配置以及它们对签出的影响。


后端服务往往模块化程度更高,可以独立运行,前端页面则不那么独立。原因有很多,如 TypeScript 配置,代码分析工具的设置方式,以及在编写工具和网页时没有考虑稀疏签出,而是假设所有文件任何时候都存在。这些针对翻译文件的配置提供了每名工程师都可以使用的增量改进。

 

稀疏签出也有缺点。首先,现在有跟踪文件没有物理地填充到磁盘上,所以不能搜索或交互。意外变更或错误的合并冲突可能会使这些文件处于错误的状态(例如,如果两个 pull 请求修改了同一个要翻译的字符串并产生冲突,现在就必须手动解决)。工程师在工作过程中必须注意这种情况。

 

每个 Git 签出命令都有开销用于检查是否应该填充或忽略更新的文件。虽然对于忽略.xlf 文件这样的简单模式来说,这种开销很小,但对于更复杂的模式,这种开销就变得非常明显了。

小结



该脚本根据推荐的 Git 配置设置 Canva monorepo。

 

结合现有的 monorepo Git 配置最佳实践,我们通过缓存将git status的时间缩短到 3 到 2 秒。虽然对于工程师来说,这比什么都不做要好得多,但随着 monorepo 越来越大,工程师越来越多,为了缩小这一数值,我们仍然有很长的路要走。

 

进行中的工作

 

这些优化为配置大型存储库设定了一条基线。但是,为了量化 Git 性能对工程师生产力的影响,并进一步分析问题和优化,我们需要能够收集 Git 操作的遥测数据。

 

Git 通过trace2格式输出跟踪信息,我们可以捕获这些信息并将其发送到中央存储进行分析。为此,我们团队一直在开发一个名为 Olly 的内部工具,用于捕获操作时间、失败及其原因,跟踪新分支的创建,等等。这有助于我们在整个组织中监控 Git 的性能,将来可以在 Git 配置发生变化时通知我们,这是量化工程师开发周期的第一步。



常见 Git 操作的平均时长

 

有了这些遥测信息,我们现在可以具体地量化 Git 性能对工程师的影响,关注痛点(上图中的 git fetch),并进一步深入分析每个操作。



git fetch 跟踪信息

 


深入研究 index-pack 操作,我们可以得到正在传输的包、对象和字节的数量。

 

此外,鉴于 Git最近暴出的漏洞,我们正致力于向所有工程师提供一个明确的 Git 版本,默认提供正确的配置,确保每个人都能获得最新的安全补丁和性能改进。


原文链接:

We Put Half a Million files in One git Repository, Here’s What We Learned

2022-08-11 11:493502

评论

发布
暂无评论
发现更多内容

为什么你辛苦肝的博客没人看?搭框架、排版、画图技巧这些你真的懂么?

码哥字节

排版规范 写作技巧 2月月更

Milvus 2.0 正式 GA

Zilliz

数据库 AI

Apache POI详解及Word文档读取示例

程序员架构进阶

Java Apache POI 2月月更

云效交付篇:流水线持续交付 | 云效快速入门

阿里云云效

阿里云 DevOps 云原生 持续交付 研发

微服务从代码到k8s部署应有尽有系列(一)

万俊峰Kevin

Go 微服务 web开发 go-zero RPC框架

Apache Pulsar 2021 年度盘点(结尾有惊喜)

Apache Pulsar

开源 云原生 中间件 社区 Apachepulsar

【架构实战营】模块七:命题作业

wgl

「架构实战营」

春节消费观察:四种愉悦感,抓住女人心

脑极体

模块七作业

whoami

「架构实战营」

Serverless 应用优化四则秘诀

Serverless Devs

Serverless

抽奖| Apache Pulsar 社区新年福袋来啦

Apache Pulsar

开源 云原生 中间件 Apache Pulsar 社区

面试突击20:进程和线程有什么区别?

王磊

预约小程序开发笔记一:背景与技术方案的选型

CC同学

Serverless 年终技术盘点 :工业、学术、社区遍地开花

Serverless Devs

云计算 阿里云 Serverless

人人都是 Serverless 架构师 | 弹幕应用开发实战

Serverless Devs

Serverless 弹幕 应用开发

低代码实现探索(三十一)管好你的组件--元信息

零道云-混合式低代码平台

Linux之free命令

入门小站

Linux

(2-2|27)🤗Huggingface.Transformers是什么?

mtfelix

300天创作

Go 学习路线(2022)

AlwaysBeta

Go golang Go 语言

Apache Druid 在 Shopee 的工程实践

Shopee技术团队

数据库 后端 Apache Druid

盘点下近几年退役的顶级 Apache 大数据项目 - 继 Sentry,Sqoop 之后,Ambari 正式退役

明哥的IT随笔

大数据 ambari sqoop sentry

职场焦虑之我对35岁危机的看法

老张

35岁危机 职场发展

架构实战营模块七 作业

Jude

架构实战营

2021 Apache Pulsar 中文社区先锋奖与年度优秀案例奖出炉!

Apache Pulsar

开源 云原生 中间件 Apache Pulsar 社区

容器编排技术 Kubernetes 学习总结|社区征文

架构精进之路

云原生 新春征文 2月日更

在线标准程序员计算器

入门小站

工具

腾讯员工怒怼加班文化事件:大厂的内卷,小厂有什么资格?

菜根老谭

暂时不在更新

你?

Python代码阅读(第74篇):单词首字母转换成大写

Felix

Python 编程 字符串 阅读代码 Python初学者

虎年开工大吉|Hoo研究院2022年0207期区块链简报

区块链前沿News

Hoo 虎符交易所 虎符研究院 虎年

7

Geek_59dec2

将 50 万个文件放在一个Git存储库中,我们做了这些_语言 & 开发_Anh Le_InfoQ精选文章