Git如何节省空间并且同时快速?

时间:2010-05-19 20:40:25

标签: git version-control compression performance github

我刚刚在Git看到了第一个http://blip.tv/play/Aeu2CAI教程。

Git如何存储所有文件的所有版本,以及它如何在空间上比仅保存最新版本代码的Subversion更经济?

我知道这可以使用压缩来完成,但这会以速度为代价,但这也说Git要快得多(尽管它获得最大值的是大部分操作都处于脱机状态)。

所以,我猜是

  • Git广泛压缩数据
  • 它仍然更快,因为uncompression + work仍然比network_fetch + work
  • 更快

我说错了吗?甚至接近?

2 个答案:

答案 0 :(得分:56)

我假设您在询问git克隆(完整存储库+结帐)是否可能小于Subversion中的签出源。或者你的意思是其他什么?

在评论

中回答了这个问题

存储库大小

首先,您应该考虑到结帐(工作版本)Subversion将pristine副本(最新版本)存储在那些.svn子目录中。原始副本在Subversion中未压缩存储。

其次,git使用以下技术使存储库更小:

  • 文件的每个版本只存储一次;这意味着如果你在10个版本(10个提交)中只有一个文件的两个不同版本,git只存储那两个版本,而不是10个版本。
  • 对象(和增量,见下文)压缩存储;编程中使用的文本文件压缩得非常好(大约是原始大小的60%,或者压缩大小减少40%)
  • 重新包装后,对象以分层的形式存储,与其他版本不同;此外,git尝试以这样的方式对delta链进行排序:delta主要由删除组成(在通常情况下,增长文件是新近顺序); IIRC三角洲也被压缩了。

性能(操作速度)

首先,任何涉及网络的操作都比本地操作慢得多。因此,例如将工作区域的当前状态与某些其他版本进行比较,或获取日志(历史记录),在Subversion中涉及网络连接和网络传输,并且在Git中是本地操作,当然在Subversion中要比在Git。 BTW。这是集中式版本控制系统(使用客户端 - 服务器工作流程)和分布式版本控制系统(使用对等工作流程)之间的区别,不仅仅是Subversion和GIT中。

其次,如果我理解正确,那么现在的限制不是CPU而是IO(磁盘访问)。因此,由于压缩(以及能够在内存中对其进行映射)而必须从磁盘读取较少数据的增益可以克服因必须解压缩数据而造成的损失。

第三,Git的设计考虑了性能(参见例如Git Wiki上的GitHistory页面):

  • 索引存储文件的统计信息,Git使用它来判断文件是否被修改而不检查文件(参见例如core.trustctime配置变量)。
  • 最大增量深度限制为pack.depth,默认为50. Git具有增量缓存以加快访问速度。有(生成的)packfile索引可以快速访问packfile中的对象。
  • Git小心不要触摸它不需要的文件。例如,当切换分支或倒带到另一个版本时,Git仅更新已更改的文件。这种理念的结果是Git只支持非常小的关键字扩展(至少开箱即用)。
  • Git使用其own version LibXDiff库,现在也用于差异和合并,而不是调用外部差异/外部合并工具。
  • Git尝试最小化 延迟 ,这意味着感知性能良好。例如,它尽可能快地输出“git log”的第一页,即使生成完整历史记录需要更多时间,您几乎可以立即看到它;它不会等待在显示之前生成完整的历史记录。
  • 获取新更改时,Git会检查与服务器共有的对象,并仅以瘦包文件的形式发送(压缩)差异。不可否认,Subversion可以(或者可能默认情况下)在更新时也只发送差异。

我不是Git黑客,我可能错过了Git用于提高性能的一些技巧和窍门。但请注意,Git大量使用POSIX(如内存映射文件),因此在MS Windows上增益可能不会那么大。

答案 1 :(得分:11)

不是一个完整的答案,但those comments(来自AlBlue)可能对问题的空间管理方面有所帮助:

  

这里有一些值得澄清的事情。

     

首先,可以拥有比SVN存储库更大的Git存储库;我希望我并不暗示那种情况从未发生过。但是,在实践中,通常情况下,Git存储库占用的磁盘空间比同等SVN存储库少。   你引用的一件事是Apache的单个SVN存储库,这显然是庞大的。但是,只需要查看git.apache.org,您就会注意到每个Apache项目都有自己的Git存储库。 真正需要的是对喜欢的比较;换句话说,检查(abdera)SVN项目与(abdera)Git存储库的克隆

     

我能够查看git://git.apache.org/abdera.git。在磁盘上,它消耗了28.8Mb   然后我检查了SVN版本http://svn.apache.org/repos/asf/abdera/java/trunk/,它消耗了34.3Mb   这两个数字都来自RAM空间中单独安装的分区,引用的数字是从磁盘中获取的字节数   如果使用du -sh作为测试手段,Git结账时间为11Mb,SVN结账时间为17Mb。

     

Apache Abdera的Git版本允许我使用任何版本的历史记录,包括当前版本; SVN只能备份当前签出的版本。但它在磁盘上占用的空间更少。

     

怎么样,你可能会问?

     

嗯,一方面,SVN创建了更多文件。 SVN结账有2959个文件;相应的Git存储库有845个文件。

     

其次,虽然SVN在层次结构的每个级别都有一个.svn文件夹,但Git repo在顶层只有一个.git存储库。这意味着(除其他事项外)从一个目录重命名到另一个目录在Git中的影响相对较小,而SVN的影响相对较小,无论如何,它已经具有相对较小的影响。

     

第三, Git将其数据存储为压缩对象,而SVN将它们存储为未压缩副本。进入任何.svn/text-base目录,您将找到(基本)文件的未压缩副本   Git有一种机制可以将所有文件(实际上是所有历史记录)压缩成包文件。在Abdera的案例中,.git/objects/pack/在4.8Mb文件中有一个.pack文件(包含所有历史记录)。
  因此,在这种情况下,存储库的大小(大致)与当前检出的代码大小相同,但我不希望总是如此。

     

无论如何,你是对的,历史可以增长到超过当前结账的总大小;但由于SVN的工作方式,它实际上必须接近两倍大小才能产生很大的不同。即使这样,磁盘空间减少也不是使用DVCS的主要原因;对某些事情来说,这是一个优势,当然,但这并不是人们使用它的真正原因。

     

请注意,Git(以及Hg和其他DVCS)确实遇到了一个问题,即检查(大)二进制文件然后删除它们,因为它们仍会显示在存储库中并占用空间,即使它们是'不是最新的。文本压缩为文本文件处理这些事情,但二进制文件更是一个问题。 (有些管理命令可以更新Git存储库的内容,但它们的开销/管理成本略高于CVS; git filter-branch类似于svnadmin dump/filter/load。)


至于速度方面,我在我的“How fast is git over subversion with remote operations?”答案中提到了它(如Linus said in its Google presentation :(这里解释)“任何涉及网络的东西都会扼杀表演”)

GitBenchmark document提到的Jakub Narębski是一个很好的补充,即使它不直接处理Subversion。
它确实列出了在DVCS性能方面需要监控的操作类型。

SO question中提到了其他Git基准。