Subversion (SVN) 是一种开源的版本控制系统,它为源文件、脚本、二进制文件和其它文件类型的存储、访问和并行开发提供便利。虽然 Subversion 非常流行,但是很多用户在导入或签入二进制文件,以及导出或签出二进制文件时,都体验到难于接受的长时间的等待。幸运的是,一旦理解了导致该性能问题的原因,就可以在您的系统中避免它。
在本文中,我将介绍在调查实际 Subversion 文件系统中与二进制文件相关的性能退化问题时的经验。我会解释系统用户和管理员所遇到的一些基本问题,然后展示对造成这些问题的起因的调查结果。最后,对调查结果作一个概述,并就优化 Subversion,以缩短访问时间和/或减少服务器消耗的空间提出一些建议。
本文主要面向将 Subversion 用于版本控制,并且希望提高存储二进制文件时的性能的系统管理员。此外,本文也适用于希望设置一个用于存储二进制文件的 Subversion 系统的任何人。如果需要阅读对 Subversion 的介绍,请参阅参考资料。
为什么存储二进制文件?
什么是二进制文件?版本控制系统通常用于文件备份、并行开发和变更管理。开发小组常常用版本控制系统来管理应用程序源文件。有时候,版本控制系统也被用于管理工具,偶尔也用于存储二进制文件。使用像 Subversion 这样的系统来存储二进制文件的一个缺点就是访问时间:从版本控制系统中取出二进制文件通常比从另一台机器或一个共享驱动器中复制或通过 FTP 传送二进制文件要慢得多。另一方面,与其它类型的文件系统相比,版本控制系统通常需要的存储空间更少。
Subversion 和其它版本控制系统可以使用只存储新版本与之前版本之间的差异,而不是整个文件的一种算法来保存文件。这里保存的差异数据被称作增量(delta),或者文件的增量。由于版本控制系统无需完整地存储每个新版本,因而用于数据存储的磁盘空间比标准文件系统要少。
大多数版本控制系统不能将二进制文件存储为增量,但 Subversion 却可以。很多系统管理员既希望节省磁盘空间,同时又希望将源文件和二进制文件保存在同一个系统中,并保持同步。要是现实中的 Subversion 的二进制存储能像理论中所说的那样工作就太好了。
现实中的情况
最近我调查了现实开发系统中 Subversion 与二进制存储相关的一些性能问题。当我开始调查时,这个系统已经运行了几个月。开发小组全体人员都受益于将源文件、脚本和二进制文件一起存储在同一个版本控制文件系统中并保持同步的做法。通过一条命令就能获得整个开发环境,这将大大减少出现错误的机会。这也有助于降低新开发人员入门的门槛。
然而,开发小组越来越担心两个问题。第一个问题是签出或导出二进制文件所需的时间,这是系统所有用户都有过体验的。与直接从另一台机器或一个共享的大磁盘上复制文件相比,使用 Subversion 要慢好几个数量级。而第二个问题只有系统管理员清楚,那就是二进制文件所占的大量空间。
发现这两个问题之后,我们开始调查情况。我们希望继续将二进制文件存储在 Subversion 文件系统中,但是首先需要发现一种办法来解决时间和空间问题。
调查的细节二进制存储格式比较
调查的第一步是考察各种不同的存储方法对将二进制文件放入 Subversion、从中取出以及按原始格式放回等操作所需时间的影响。我们尝试了四种方法:将二进制文件以大型目录结构的形式放入 Subversion,创建一个包含目录结构的文件然后将该文件放入 Subversion 中,压缩单个文件,以及以增量形式保存二进制文件,而不是每次将整个新版本存入 Subversion 中。
表 1显示了多种在 Subversion 中存储二进制文件的方法。它还显示了将二进制文件移入和移出 Subversion 所花的时间。这些存储方法的细节如下:
压缩的 tar 格式 - 导入 - 导出:将二进制目录组合成单个压缩的 tar 文件(一个 tar.gz 文件),然后使用import命令将其存入 Subversion 中。之后,使用export命令从 Subversion 中取出该文件,然后从压缩的 tar 文件中检索原始目录(也就是说,文件被解压。) tar 格式 - 导入 - 导出:与前一种方法几乎相同,但是在这里,文件没有被压缩,所以它是 tar 文件,而不是 tar.gz 文件。 导入 - 导出:使用import命令将二进制目录原样存入 Subversion 中。然后,使用export命令检索它们。 高效签入:使用一个高效签入脚本将二进制目录存入 Subversion 中。然后使用export命令检索二进制文件。(关于高效签入脚本,请参阅下面的内容。)我们收集了很多结果,以确定被证实的发现。表 1 显示了一个代表性的例子:
注意,每当使用import命令将一项内容存入 Subversion 中,就是存储该项的整个副本,而不会尝试以增量形式存储它。因此,import命令比较快,但是空间效率不高。Subversion 附带有一个脚本,该脚本尝试以高空间效率签入文件。高效签入脚本将要存入 Subversion 的版本与已有的版本进行比较。然后,以两者之间的增量的形式存储新版本。
时间测试结果
表 1 显示的结果清楚地表明,所使用的二进制存储格式对于将二进制文件移入和移出 Subversion 所需的时间有很大的影响。时间效率最高的方法就是创建一个压缩的包含二进制的文件。即使创建一个单独的、不压缩的包含二进制的文件,所花的时间也仍然少于以初始结构导入二进制文件所需时间的十分之一。
这些结论之所以正确,是因为很多 Subversion 的导入处理时间都花在要处理的目录的重现上,所以创建单个文件反而可以大大节省时间。使用 Subversion 的高效签入脚本会导致难于接受的等待时间。该脚本之所以要花费那么多时间,是因为它实际上要将整个二进制文件的副本导出到本地磁盘,以进行比较。
这些研究只考虑不同的存储方法对向 Subversion 存储、访问和检索二进制文件所需时间的影响。我们仍然需要调查以不同存储格式存储二进制文件所需的大量服务器磁盘空间。