Facebook应用Mercurial经验谈

Facebook的主要源代码库是巨大的 - 甚至比Linux内核还要大,一周有成千上万犯跨越成百上千的文件的提交。

两年前Facebook还是使用Subversion+Git,很快成为瓶颈,Facebook代码库已经成长为内部依赖关系是非常复杂。需要花很多时间使之更模块化,才能适合一般的源代码管理工具,但是Facebook认为也有他们这样使用单个存储库的好处。他们的特点是一个不断分裂变大的单一源码库,现有的大部分源码管理工具通过限制代码结构的方式并不适合他们。

Facebook开始自己寻找新的方案,考虑到程序员都习惯Git界面,花了很长时间提升Git,但是很难看到提高的工作规模。想来想去,Facebook得出的结论是:Git是不适合内部一个巨大项目的。

最后,他们选择了Mercurial。

Mercurial(水银)是一个类似于Git的分布式源代码管理系统。它主要是使用清晰的模块化的Python 编写,使其成为易于扩展。当Facebook开始使用水银,发现它比Git在几个显着的领域慢。为了缩小这种差距,Facebook在过去一年半的时间已经贡献了超过500补丁。

对于大到象Facebook这样的的存储库,一个主要的瓶颈是简单地找出哪些文件发生了变化。 Git是检查每个文件,自然地随着文件数量的增加变得越来越慢,而Perforce的“秘籍” ,迫使用户告诉它他们将编辑的文件。Git的方法不具有扩展,Perforce的方法也并不友好。Facebook 通过监控文件系统更改解决这个问题。

Facebook让Watchman守望者的集成取得了Mercurial的命令状态比Git的状态命令更快,超过5倍。

提交率和历史资料的庞大规模也带来了挑战。Facebook每一天有成千上万的提交,存储库变大使得clone和Poll等操作变得越来越痛苦。Faceook创建了remotefilelog扩展水银,改变了clone和pull命令,只下载提交的元数据,而忽略了占下载大头的所有文件的变化。再通过使用memcache作为基础设施,在中央Mercurial服务器的前面设置一个缓存层,这样即使中央存储库出现故障, memcache将继续提供许多文件内容。启用remotefilelog扩展后员工在Facebook已经实现Mercurial clone和poll要快10倍,从几分钟到几秒钟,这是因为remotefilelog存储数据在本地磁盘上的方式。

水银有几个这种漂亮的抽象扩展。最值得注意的是filelog类。是一种数据结构,表示一个特定文件的每个版本。每个版本的文件是由一个唯一的哈希标识。对于给定的一个散列时,filelog可以重建一个文件的请求版本。remotefilelog扩展是替换其的另一种实现,具有filelog相同接口。它接受一个哈希,但不是从本地数据文件的版本重建,它从本地缓存或远程服务器获取该版本。当我们需要从服务器请求大量的文件,我们这样大批量地做,以避免许多请求的开销。