微软打造了全球最大的Git代码库

丹棱君有话说:今年 2 月,微软宣布将用 Git 管理 Windows 源代码。随后,Visual Studio 宣布开发 “Git 虚拟文件系统(GVFS)”,并将在终极项目和超大型团队中推行 Git 。5 月,Windows 开发团队基本完成 GVFS 部署,超过 3500 多名工程师开始使用。截止 5 月 24 日,系统收到了 25 万多次的 Git 提交,平均每天推送代码 8421 次,接受合并请求 2500 次。微软已经将 GVFS 开源,并邀请其他感兴趣的公司来使用,并加入贡献行列。GVFS 是如何管理超大规模数据的?系统的性能在最初的版本基础之上做了怎样的改进和优化?数千名 Windows 工程师对 Git / GVFS 真实评价如何?今天,丹棱君为大家“请来” Visual Studio 公司副总裁 Brain Harry 先生,讲一讲我软打造的全球最大 Git 代码库的来龙去脉,掌声有请~

 

今年 2 月,微软出人意料地宣布,将用 Git 管理 Windows 的源代码。

 

当月,我撰文宣布将在终极项目和超大型团队中推行 Git,并为此开发了 “Git 虚拟文件系统”(简称 GVFS) 。GVFS 和一系列 Git 增强功能通过虚拟 .git 文件夹和工作目录让 Git 能管理好超大型代码库。开发者可以只下载自己需要的那部分,而无需下载整个库、提取所有文件。

 

那时候,GVFS 仍是一个构想,处于实验阶段,尚未经实践检验。我们验证了几个大型代码库,但未在一定量级的工程师团队中推广,所以有的只有成功的信念。现在,我们终于有了实质性证据。 

 

除了和大家分享我们的成果,我们还要宣布之后的 GVFS 工作计划,包括进一步开源、接受代码贡献以及为微软及其合作伙伴和客户进行系统改进和功能优化。

 

Windows 已登陆 Gi

 

Windows 登录 Git 的前三个月,我们基本完成了 Windows 开发团队的 Git / GVFS 部署。

 

首先来回顾一下,Windows 的代码共有 350 万份文件,如果全部 checkout 到 Git,生成的代码库将近 300 GB 。此外,由 4000 多位工程师组成的 Windows 开发团队每天在 440 个分支上生成 1760 个“实验室版本”和成千上万的合并请求验证版本。文件数量、代码仓库大小和工程活动,每一个都是不小的挑战,更何况这些因素是叠加在一起的。因此,确保开发者的工作效率是摆在我们面前的巨大难题。在迁移到 Git 前,我们在 Source Depot 上创建了 40 多个代码库,并利用工具进行管理。

 

今年 2 月,我们把所有代码都放在一个版本库中,供数百位工程师使用,每天生成小于 10% 的每日构建。从那时起,我们开始分阶段在整个 Windows 开发团队中推行 Git 部署。 

 

第一次,也是最大的一次飞跃,发生在今年 3 月 22 日,我们开始在拥有 2000 位工程师的 Windows OneCore 团队部署 Git 。星期五,这些工程师还在 Source Depot 上工作,过完周末,星期一回来就要面对基于 Git 的全新体验。整个周末,我的团队提心吊胆,祈祷工程师星期一还能正常工作,以免将一腔怒火发泄到我们头上。事实上,Windows 开发团队为防止意外发生做了充分备案。很幸运,所有备案都没有启动。

 

坦率地说,第一天系统运作正常,工程师们的工作也进展顺利,这让我颇为惊讶。当然,我们也碰到了问题。例如,因为团队规模和工作性质的关系,Windows 经常需要跨分支进行超大型合并(10000 次修改中有 1000 次冲突)。第一周我们就发现负责合并请求和解决合并冲突的 UI 界面根本无法支持如此巨大的数据量。为了让 UI 正常显示,我们不得不虚拟化列表并逐步抓取数据。几天时间后,这个问题得到了解决。整体而言,那一周大家的反馈超出了我们的预期。

 

为了了解 Git 的部署是否成功,我们对开发团队进行了“满意度”的调研,同时也挖掘了其他信息。部署两周后,第一次调研结果出来了:

我不会为这些数字欣喜若狂,Windows 团队刚经历翻天覆地的变化,他们必须学习全新的工作方式,这个转变过程本身就是一项巨大工程,能给出这样的评价和反馈,我已经相当满意了。尽管 2000 多位受访人员只给了我们 251 份反馈,但这就是调研的现实情况。

 

除了调研,我们还通过观察“工程活动”,也就是工程师们是否能顺利完成工作,来判断 Git 的部署成功与否。例如,我们测算了正式分支的“签入”数量,当时,有一半团队还在用 Source Depot,有一半已经迁移到 Git,于是我们观测了两个平台的正式分支的“签入”数量。从下图可以看到 Source Depot 上的签入数出现大幅下降,而 Git 上的合并请求数激增。总体而言,两者的总和保持恒定。我们认为这些数据说明系统运行正常,不存在大的阻碍。

今年 4 月 22 日,我们迎来了 1000 多位工程师新用户。今年 5 月 12 日,又有三、四百位工程师加入我们。每个阶段我们都经历了相似的进展模式,现在已有 3500 多位 Windows 工程师在 Git 上工作。其他团队正在忙于他们目前的交付任务,还在寻找迁移的最佳时机。

 

在这个规模上,系统运行得非常棒。 给大家看一组数字:

 

  • Windows 登录 Git 的前三个月,代码库收到超过 25 万次 Git 提交。

  • 平均每天推送代码 8421 次。

  • 6600 审阅者接受合并请求: 平均 2500 次 / 工作日。

  • 活跃公开分支:4352 个。

  • 完整编译版本:1760 个 / 天。

 

这个超大代码库里正发生着海量活动。 

 

GVFS 的大规模性

 

满意度调研也收到了负面反馈,背后的原因有:比如,一些人无法安装 Git 、一些人对学习新知识和接受新事物感到抗拒,但最重要的还是性能问题,我想就此多说几句。 Git 推广时,很多性能还未完善。我们针对 Git 运行的关键性能指数进行检测,以下是日志系统收集的 3500 多位工程师使用 GVFS 的数据。

表格中的“目标”值,是系统正常运行需达到的最低值,低于这个值时,系统运行会变慢,甚至无法使用。我们也可以看到,过去 7 天 80% 的结果和前 7 天的差值对比,数据说明系统正变得越来越慢,我将在下文解释这一点。

 

先说一下背景,用原生的 Git (“vanilla Git”)实现 ,很多命令耗时 30 分钟或几个小时,有些甚至永远无法执行。相较于此,如果大部分命令在 20 秒内完成,就已经是一个巨大的进步。但是对于用户来说,每次运行命令都需要等待 10 - 15 秒,仍然是非常糟糕的体验。

 

第一次推广的结果,成为我们的主要收获之一。如果你曾读过我介绍 GVFS 的博文,就会了解我们在 Git 和 GVFS 里做的许多工作,是让系统的运行量是和被读取的文件数成正比,而非代码库里的文件数。 当工程师们不断抓取代码库,触及更多内容时,会导致 “over hydration” 的问题。 简单来说,那些被读取但未使用或是被修改的文件会日益堆积,导致系统性能降低。虽然,工程师可以自己“清理”,但操作麻烦,少有人做,所以系统变得越来越慢。

 

基于此,我们进行了性能提升,称之为 “O(modified)”。改善后,可以使许多关键命令的执行成本与修改过的文件数成正比(也就是前文提到的未提交的编辑) 。 目前,虽没有相关结果的统计数据,但早期试点用户的反馈良好,我们将向整个团队做推广。

 

我从上文中的表格挑选了几个例子,将性能结果复制到 “O(hydrated)” 列,另增了一个 O (modified)列,结果来自经过 O(modified)优化的同样的命令。所有的数值都以秒为单位。正如你看到的,性能全方面得到提升—— 有些很微小,但有些高达两倍,甚至接近五倍。这些提升很可能改变大家对性能的观感。我并非志得意满(除非测试结果降至一秒以内),但这已是非常大的进步了。

 

另一个关键性能改善体现在分布式研发方面。Windows 的开发团队分散在全世界各地 —— 美国、欧洲、中东、印度、中国等。横跨超远距离、在非理想的网络带宽上拉取海量数据是个巨大问题。为此,我们为 GVFS 开发了一个 Git 代理服务,可以在用户端缓存 Git 数据。为避免在高峰负载时段影响终端用户的体验,我们降低了 Visual Studio Team Service 主服务中的一些会占用大量带宽的服务,例如 Build Server 。我们在世界各地共有 20 个 Git 代理,目前已并入 Team Foundation Server Proxy 。

 

下面我将举例说明它的作用。这个 Windows Team Services 帐户位于美国西海岸的 Azure 数据中心。从图表中可看出,对于一个 Windows 工程师,80% 的 Clone 操作需要 127 秒完成。由于绝大部分 Windows 工程师都在雷德蒙工作,所以这个数字代表了他们的体验。我们曾在北卡罗来纳州办公室做过测试,那里不仅距离远而且网络带宽低很多。如果不设置代理,在北卡罗来纳州进行一次 Clone 则需要近 25 分钟。配置、更新代理后,Clone 只花了 70 秒(比雷德蒙团队还要快,因为他们没有使用代理,需要通过数百公里的互联网才能达到 Azure 数据中心)。从近 25 分钟到 70 秒,相当于提升了 95% 。当 GVFS 访问“故障”文件时,我们也看到类似的改进。

 

由此可见,共用 Git 与 GVFS 完全适用于超大规模代码库,而且结果证明工程师能有效工作。在提升工程师们的满意度方面,我们仍然有许多工作要做,接下来推广 O(modified)将是重要一步。 

 

快来试试 GVFS 吧

 

如果想尝试 GVFS,你只需从 https://github.com/Microsoft/GVFS 下载、安装,创建一个 Visual Studio Team Services 帐户和一个 Git 版本库即可。 GVFS 发布至今,进展很多,关键改进如下:

 

定期更新已发布的代码库 —— 转向“面向社区开放式的开发(development in the open)”。目前所有的最新修改(包括新的 O (modified))都会发布到公共代码库,并将定期更新。 

 

发布 GVFS 之时,我们还未做好接受外部代码贡献的准备。现在,我们的基础架构都已到位,热烈欢迎大家和我们一起改进 GVFS 。

 

GVFS 依赖于我们称之为 GVFlt 的 Windows 文件系统驱动程序。之前发布的这个驱动程序还没有做任何的数字签名。 自然,大家在试用过程中会碰到问题。5 月 24 日,我们发布了一个基本消除问题的签名版本,例如,大家在安装前无需禁用 BitLocker 。尽管有了一个签名版的 GVFlt 驱动,但这只是一个临时的方案。预计细节问题处理完毕之后,此项功能会被并入今后的 Windows 版本。

 

从讨论 Git Merge 开始,我们就在更广泛的 Git 社区探讨 Git 和 GVFS 的扩展问题。我们和其他面临类似难题的大型科技公司(如 Google 和 Facebook)进行了交流,分享经验和解决方案。同时,我们与主流 Git 客户端工具厂商达成合作,确保 GVFS 的顺利使用,包括:

 

  • Atlassian SourceTree —— SourceTree 是第一个使用 GVFS 进行验证的工具,并已发布了更新版本。

  • Tower —— Tower Git 团队正在打造下一个 Windows 版应用,并将支持 GVFS 。不久大家就可以在 https://www.git-tower.com/windows 下载到支持 GVFS 的免费更新。

  • Visual Studio —— 当然,如果我们自己集成 Git 的 Visual Studio 能支持 GVFS 。六月初推出的预览版的 VS 2017.3 已加入 GVFS 。

  • Git for Windows - 作为我们扩展 Git 的部分工作,我们还为 Git for Windows 贡献了代码(Git 命令行),包括支持 GVFS 。现在,我们还有一个 Git for Windows 的专有派生,但随着时间的推移,我们将把所有修改贡献回主线。

 

总结

 

我们正将微软其他大型研发团队的代码库部署到 Git 上。取得的进展有:

 

  • Windows 登录 Git 的前三个月,已有 3500 多位 Windows 开发工程师开始使用 Git 。

  • 部分性能得到显著提升,推出 Git 代理 。

  • 以最新代码更新了多个开源项目,并邀请社区贡献代码。

  • 推出签名版的 GVFlt 驱动程序方便大家试用。 

  • 社区合作,开始在主流的工具像 SourceTree,Tower,Visual Studio 内加入对 GVFS 的支持。

  • 在 https://www.visualstudio.com/learn/git-at-scale 发布了多篇详解 Git 和 GVFS 扩展的技术文章。 

 

这场微软内部激动人心的转变,对我的团队和 Windows 开发团队来说,都是一个极富挑战的项目。我为所取得的进展感到高兴,也非常愿意倾听大家对我们未来工作的建议。如果你也需要使用大型代码库,而希望迁移到 Git 上,我会推荐你试试 GVFS 。现在,Visual Studio Team Services 是唯一支持 GVFS 协议增强功能的后端实现。如果我们收到足够多的需求,会在未来的 Team Foundation Server 中加入相应的支持,其他第三方的 Git 服务提供商也是我们愿意合作的对象。

立即访问http://market.azure.cn

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Algorithms   本次README修订为算法Algorithms的第100次commit,首先我们庆祝自2016年8月4日本建立以来Dev-XYS在算法学习方面取得的显著进步!   这里有各种算法的C++代码,任何人可以在自己的任何程序中使用,欢迎大家指出代码中的错误以及有待改进的地方。   本内所有代码的授权方式为Unlicense,大家如果使用我的代码开发自己的软件挣了大钱,或是参考我的代码在NOI中得了金牌,我都会很高兴的。使用这里的代码之后,你可以自主选择是否公开源代码。总而言之,你可以把这里的代码当作你自己写的一样,无论怎样使用都是被允许的。但是,我不对本代码的正确性负责。大家要是使用我的代码开发软件而导致程序崩溃,或是参考我的代码在考试时出错,请不要向我抱怨。如果你愿意,遇到问题可以在Issues中提出来,我们共同解决。我们不赞成Pull Request,因为本主要储存作者已经学习的算法,全部代码均由作者本人负责维护与更新。   以下索引提供了本内算法的中文名,方便大家查找。更新可能有很长时间的延迟,不保证所有算法的名称都在列表中出现。 Index --------------------------Contents-------------------------- --------------------------FileName-------------------------- AC自动机 Aho-Corasick-Automation 单源最短路径(SPFA) Bellman-Ford(Queue-Optimised) 单源最短路径(Bellman-Ford) Bellman-Ford 使用Edmonds-Karp进行二分图匹配 Bigrpah-Matching(Edmonds-Karp) 普通的二叉搜索树 Binary-Search-Tree 广度优先搜索 Breadth-First-Search 冒泡排序 Bubble-Sort 桶排序 Bucket-Sort 组合数的递推求解 Combination(Recursion) 枚举组合 Combination 基本的复数类 Complex-Number 割点 Cut-Vertex 深度优先搜索 Depth-First-Search 堆优化的Dijkstra算法 Dijkstra(Heap-Optimised) 并查集 Disjoint-Set-Union 最大流Edmonds-Karp算法 Edmonds-Karp 欧拉函数 Euler's-Totient-Function 有向图的欧拉回路 Eulerian-Tour(Digraph) 拓展欧几里得算法 Extended-Euclid 简单的快速幂 Fast-Exponentiation 树状数组 Fenwick-Tree 所有结点对之间的最短路径(Floyd) Floyd-Warshall 凸包算法(Graham扫描法) Graham-Scan 辗转相除法求最大公约数 Greatest-Common-Divisor 堆排序 Heap-Sort ISAP算法 Improved-Shortest-Augmenting-Path(Naive) 插入排序 Insertion-Sort 字符串匹配(KMP) Knuth-Morris-Pratt 最小生成树(Kruskal) Kruskal 最近公共祖先(Tarjan) Least-Common-Ancestor(Tarjan) 使用后缀数组求解最长公共子串 Longest-Common-Substring 最长上升子序列(n·log(n)) Longest-Increasing-Subsequence(n·log(n)) 倍增法求最近公共祖先 Lowest-Common-Ancestor(Doubling) 朴素的矩阵乘法 Matrix-Multiplication(Naive) 归并排序 Merge-Sort 最小堆 Min-Heap 乘法逆元 Modular-Multiplicative-Inverse 仅支持单点修改的可持久化线段树(维护区间和值) Persistent-Segment-Tree(Sum) 试除法素数测试 Prime-Check(Naive) 线性的素数筛法 Prime-Sieve(Linear) 队列的基本操作 Queue 快速排序的优化版本 Quick-Sort(Extra-Optimised) 快速排序的随机化版本 Quick-Sort(Randomized) 快速排序 Quick-Sort 使用向量叉积判断两个有向线段的时针关系 Segment-Direction 线段树维护区间最大值 Segment-Tree(Maximum) 线段树维护区间最小值 Segment-Tree(Minimum) 线段树维护区间和值 Segment-Tree(Sum) 普通的选择算法 Selection Eratosthenes素数筛法 Sieve-of-Erotosthenes 指针版的单向链表 Singly-Linked-List(Pointer) 跳表 Skip-List ST表 Sparse-Table 伸展树 Splay 博弈论SG函数 Sprague-Grundy 栈的基本操作 Stack 递推法求解无符号第一类斯特林数 Stirling-Number(Cycle,Unsigned,Recursion) 递推法求解第二类斯特林数 Stirling-Number(Subset,Recursion) 倍增法求解后缀数组 Suffix-Array(Doubling) 倍增法求解后缀数组(附带Height数组) Suffix-Array-with-Height(Doubling) 使用Tarjan算法求解强连通分量 Tarjan(Strongly-Connected-Components) 数组版的字典树 Trie(Array) 指针版的字典树 Trie(Pointer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值