`

Google 为什么把几十亿行代码放在一个库?

阅读更多

本文原文链接:ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html,如有侵权,则可删除。

00 前言

《ACM通信》有一篇论文《为什么 Google 要把几十亿行代码放在一个库?》,作者是谷歌基础设施小组的工程师。作者详细讲述了Google的代码为什么全部放在一个库里面。

01 概述

谷歌最早使用 CVS 进行代码管理,1999年改为 Perforce。那时是一台 Perforce 主机,加上各种缓存机。

当时,全公司的代码就在一个仓库里面,后来一直沿用这种做法。由于规模不断增长,Perforce 已经无法满足需求,谷歌就开始使用自己开发的版本管理系统 Piper。

Piper 架设在谷歌自己的分布式数据库系统(以前叫 Bigtable,现在改名 Spanner)之上,分布在全世界10个数据中心,保证世界各地的谷歌员工都有良好的访问速度。

目前,这个代码仓库包含10亿个文件、3500万次提交记录,大小为86TB,用户达到几万人。工作日每秒有50万次请求,高峰时80万次,大部分来自自动构建和测试系统。

谷歌90%以上的代码,放在 Piper 里面。对于那些开源的、需要外部协作的项目,代码放在 Git,主要是 Android 项目和 Chrome 项目。Git 的特点是,所有历史记录都会复制到用户的本地机器,所以不适合大型项目,必须拆分成更小的库。以 Android 为例,该项目一共包含800多个独立的仓库。

02 Piper 的设计

2.1 结构

整个仓库采用树状结构。每个团队有自己的目录。目录路径就是代码的命名空间。每个目录都有负责人(owner),他负责批准该目录的文件变动。

2.2 权限控制

Piper 支持文件级别的权限控制。99% 的代码对所有用户可见,只有少部分重要的配置文件和机密的关键业务,设有访问限制。

如果机密信息不小心放上了 Piper,文件可以被快速清除。并且,所有的读写都有日志,管理员能够查到谁读过这个文件。

2.3 工作流

Piper 的工作流(workflow)如下图。

开发者先创建文件的本地拷贝,这叫做”工作区”(workspace)。完成开发后,工作区的快照共享给其他开发者进行代码评审。只有通过了评审,代码才能合并到中央仓库。

2.4 客户端

大多数开发者通过一个叫做 CitC 的客户端,访问 Piper。开发者通过 CitC 浏览和同步 Piper 上的文件,但是编辑和修改是在自己工作区,里面只保存有变动的文件(一个工作区一般不超过10个文件)。CitC 带有云储存机制,每个工作区就是云上的一个目录。通过代码评审以后,这些文件才从 Citc 合并进 Piper。

2.5 主干开发

Google 采用”主干开发”(trunk-based development)。代码一般提交到主干的头部。这样保证了所有用户看到的都是同一份代码的最新版本。

“主干开发”避免了合并分支时的麻烦。谷歌一般不采用分支开发,分支只用来发布。大多数时候,发布分支是主干某个时点的快照。以后的除错和功能增强,都是提交到主干,必要时 cherry-pick 到发布分支。与主干长期并行的开发分支,在谷歌极少见。

由于不采用"分支开发",谷歌引入新功能,一般在代码中使用开关控制。这避免了另起一个分支,也使得通过配置切换功能变得容易,一旦新功能发生故障,很容易切换回旧功能。等到新功能稳定,再彻底删除旧代码。谷歌有类似A/B测试的路由算法,评估代码的表现,由于存在配置开关,这种测试很容易实现。

2.6 代码评审

所有代码合并进仓库之前,都必须进行代码评审。大部分评审对所有人开放,任何谷歌员工都可以对代码提意见或者提交变动。

代码评审的依据是《Google 代码风格指南》。谷歌有一个叫做 Critique 的工具,可以查看每一行代码的历史演变。

2.7 自动测试

评审完成后,会自动运行测试。通过测试以后,代码就合并进了 Piper 仓库,整个过程不需要人工干预。

03 单一代码仓库的优点

(1)统一的版本

整个公司的代码,有统一的版本和路径,不存在找不到文件的最新版本这样的问题。

(2)广泛的代码共享和复用

任何人都可以浏览和使用全公司的代码,这大大促进了代码的共享和复用。

(3)简化的依赖管理

如果你是库文件或者 API 的作者,因为所有人的代码都在一个库里面,所以很容易找到依赖你的所有下游代码。

每当代码变动,所有依赖你的代码都会自动构建。如果有大量的构建失败,那么系统会自动撤销这次提交。这样也保证了所有代码依赖的都是最新版本,避免依赖不同的版本所导致的冲突。

另外,由于代码的边界很清楚,所以不会发生循环依赖。而且,API的作者也很容易发现,别人怎么使用他的API。

(4)原子性变动

由于每次代码变动所导致的影响,都在一个仓库里面,所以都属于原子性的变动。因此,很容易撤销,或者预先测试它所造成的影响。

为了防止错误提交,谷歌引入了”预提交”(即在提交之前,先分析一下依赖它的代码是否会构建失败)。

(5)大规模代码析构

单一代码仓库为查找和分析代码,提供了巨大的方便。

Google的静态分析引擎 Tricorder 定时运行,对代码进行分析。比如,C++ 11 标准公布以后,很容易找到所有需要改进的变量声明语句,进行性能优化。该引擎还对许多错误提供"一键修正"的功能,同时产出大量的统计数据。

此外,编译器团队也会对不同语言的所有代码进行分析,找出不合理的代码和过时的API。

04 单一代码仓库的缺点

单一代码仓库的主要缺点是,所有工具都必须自己写,因为市场上没有能够管理这种规模的代码仓库的软件。

05 总结

单一代码仓库,适合提倡透明开放的大型软件公司,不适合小公司和有大量私密代码的公司

分享到:
评论

相关推荐

    Google C++编程规范.pdf

    2. **代码注释**:对于复杂的逻辑或不直观的操作,添加简短的注释来解释为什么这样做。 3. **避免过时的注释**:随着代码的变化,及时更新相关的注释,避免出现与代码实际行为不符的情况。 #### 八、格式 代码格式...

    Google C++ 编码规范

    建议如果需要重载一个函数,考虑将函数名改为包含参数类型的信息,例如使用 `AppendString()` 和 `AppendInt()` 而不是 `Append()`。 #### 八、缺省参数 禁止使用缺省函数参数。虽然缺省参数可以减少函数定义的...

    KML 生成软件的使用

    最后碰到的一个令人头疼的问题就是保存文件,开始想参考第十一章的 POPPAD 程序,看来没有把这个程序吃透,就放弃了。准备使用《WINDOWS 核心编程》上面的文本框来输出生成的经纬度文件,当我安装号运行程序库并配置...

    Android简单计算器

    在Android平台上开发一个简单的计算器应用是一项基础且实用的任务,它能帮助我们理解Android应用程序的基本架构、用户界面设计以及事件处理机制。在这个项目中,我们主要会涉及到以下几个关键知识点: 1. **Android...

    matlabhill代码-h1b_statistics:分析过去几年的数据以计算认证签证申请的前十大职业和前十个州的机制

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    nmea_gmaps:获取 NMEA 句子并将它们放在谷歌地图上

    `nmea_gmaps` 是一个Python项目,其目的是从NMEA数据流中提取这些信息,并将它们实时地展示在谷歌地图的JavaScript API上。 该项目的核心在于解析NMEA句子。NMEA句子通常以"$"开头,后面跟着一个或多个数据字段,每...

    matlab生成的c代码编译失败-h1b_statistics:h1b_statistics

    作为数据工程师,要求您创建一种机制来分析过去几年的数据,特别是计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以...

    Angular Source Code Tour [pdf]

    **Tsickle** 是一个工具,用于将 TypeScript 代码转换为带有 JSDoc 注释的 JavaScript 代码,这样就可以在没有 TypeScript 支持的环境中使用这些代码。 #### 十九、TS-API-Guardian **TS-API-Guardian** 是一个...

    Google+Android+SDK开发范例大全+8.rar

    《Google+Android+SDK开发范例大全+8.rar》是一个包含深入Android SDK开发实例的资源包,主要针对Google的Android操作系统进行程序设计的学习和实践。本文将详细解析这个压缩包中可能涵盖的知识点,帮助开发者深入...

    grub4dos-V0.4.6a-2017-02-04更新

    执行时可以不用输入扩展名,比如输入test如果当前路径下有一个test.g4b就会自动使用。 2013-10-17 1.修改代码支持新版HOTKEY。 2013-07-10 1.insmod现在支持长文件名(以前最多11个字符,现在没有限制). 2....

    matlabhill代码-Insight_project:洞察力代码挑战项目

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-InsightProject:适用于数据工程师的InsightProject代码测试

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-DICodingChall:DICodingChall

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-test:测试

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-DI:的

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-testing123:测试123

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-H1BInsightDataScience:H1BInsightDataScience

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    matlabhill代码-h1binsight:h1binsight

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

    从零开始学习jQuery

    1. **轻量级**:jQuery的文件大小非常小,压缩后只有几十KB,加载速度快。 2. **易于使用**:jQuery拥有一个非常友好的API,即使对于初学者来说也容易上手。 3. **强大的选择器**:jQuery的选择器与CSS选择器相似,...

    matlabhill代码-insight_coding:Insight_coding

    作为数据工程师,您需要创建一种机制来分析过去几年的数据,具体计算两个指标:经认证的签证申请的前十名职业和前十名国家。 您的代码应该是模块化的,并可以在将来重用。 如果报纸获取了2019年的数据(假设可以使用...

Global site tag (gtag.js) - Google Analytics