GitHub工程团队执行了一个称作Cyclops的项目,实例并且更新许多方法,改进大型单一存储库的性能,减少推送失败,并且提高单一存储库更新速率至少一个量级,使得当前架构仍有多年的发展空间,来应对目前最大的单一存储库增长。
GitHub上目前已经有超过2亿个程序代码存储库,并且服务超过5,600万用户,官方提到,像GitHub这么大的系统,有些问题可能要在部分极限情况才会出现,像是在每天有上千开发者对同一存储库更新时。几个拥有庞大单一存储库的用户向GitHub反应,他们存储库的性能问题,影响他们推送操作,而GitHub的github/github存储库,本身也是个庞大的单一存储库,甚至连GitHub自己偶尔也会遇到推送失败。
为此GitHub展开了调查行动,除了与内部团队,他们也与用户合作,共同了解并优化他们在GitHub上的操作,经过了一些调整,不正常的推送失败仍然存在,因此GitHub决定以项目处理这个问题,创建了Cyclops项目,跨Git系统部门合作,包括Git存储、协议和客户端团队,并与上游Git项目贡献者和工程师,共同寻找问题的解决方案。
GitHub首先改善了存储库维护工作,在默认情况下,GitHub每执行50次git push操作,或是在收到40 MB解压缩文件后,系统就会执行一次存储库维护例程,以更新packfile并且维持复制和截取的性能,并清理存储库中的复制资料,而维护时间会依存储库的大小而有不同,可能需要数秒钟到数分钟的时间。
对大量开发人员共同使用的大型单一存储库来说,不需要太久的时间,就能累计50次推送操作,因此在开发人员持续推送更新的同时,存储库也会频繁地进行维护工作,有些存储库无法在最大时间限制内完成维护工作,使得推送和参照更新性能受影响,而现在GitHub通过改进git repack和重新尝试维护调度,将维护故障几率降低接近零。
大部分的维护故障是由于git repack指令造成,在存储库维护期间,GitHub系统会执行git repack来压缩松散对象,而为了将一组对象压缩在一起,Git需要寻找相对应的对象,部分对象不是以完整的内容存储,而是存储其他相关对象的增量内容,寻找这些增量内容需要花耗时间,因此将每个对象互相比较很快地变得不可行。
Git通过在打包对象的数组,使用滑动窗口算法来搜索增量与基础对象配对,这样的启发式方法,可以迅速筛掉窗口中的部分增量候选对象,但是缺点是必须花费较多的CPU资源进行比较,GitHub调校了一个最佳参数,以限制高成本运算的次数,减少花费的CPU时间,并且略增加生成的packfile大小,这项改进消除了几乎所有维护故障。
在过去,当存储库因为特定原因导致维护失败,系统在7日内不会再次执行维护,但是现在的单一存储库已经无法等待这么久的时间,因此GitHub对特定类型的维护失败,通常是因为在维护期间,所产生的大量推送流量造成的失败,加入一种伪失败状态,在这种状态,存储库会每4小时重新尝试维护一次,最多3次,而这消除了剩余的维护故障。
另外,由于早前GitHub对服务器的推送限制,也产生了许多推送相关的错误。官方解释,因为GitHub是一个多租户服务,为了确保来自单一用户的操作,不会垄断服务器上的资源,影响其他用户的使用,因此特别设置参数,减慢推送操作的速度,但经过GitHub的调查,现在系统架构已经够强健,即便立即处理所有推送操作,也不会产生任何问题,于是GitHub现在删除了相关程序代码,进而减少了许多与推送相关的错误。
经过了这些更改,大型单一存储库用户,几乎不再发生推送失败,官方提到,其中有一些故障是因为随机的互联网问题所引起,这超出GitHub可控制范围。GitHub也仍在处理一些剩余的故障问题,同时继续提升GitHub的执行速度,官方还提到,他们正在分解使用Ruby语言开发的单体程序,并且以Go重新编写新的微服务程序,以提高存储库性能。