Subversion 是为数不多的能使用增量算法存储二进制文件的版本控制系统之一。不幸的是,用户发现这样做时会导致性能受到不小的损失。在本文中,高级开发人员
David Bell 解释为什么在处理二进制文件时 Subversion 的性能会受损,并推荐了几种方法来避开这个问题。
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 显示了一个代表性的例子:
表 1. 比较不同存储格式消耗的时间
方法 |
输入时间 |
输出时间 |
压缩的 tar 格式 - 导入 - 导出 |
1m 28s |
0m 30s |
tar 格式 - 导入 - 导出 |
1m 51s |
0m 47s |
导入 - 导出 |
28m 0s |
9m 30s |
高效签入 - 导出 |
2h 15s |
9m 30s |
注意,每当使用 import
命令将一项内容存入 Subversion 中,就是存储该项的整个副本,而不会尝试以增量形式存储它。因此,import
命令比较快,但是空间效率不高。Subversion 附带有一个脚本,该脚本尝试以高空间效率签入文件。高效签入脚本将要存入 Subversion
的版本与已有的版本进行比较。然后,以两者之间的增量的形式存储新版本。
时间测试结果
表 1 显示的结果清楚地表明,所使用的二进制存储格式对于将二进制文件移入和移出 Subversion 所需的时间有很大的影响。时间效率最高的方法就是创建一个压缩的包含二进制的文件。即使创建一个单独的、不压缩的包含二进制的文件,所花的时间也仍然少于以初始结构导入二进制文件所需时间的十分之一。
这些结论之所以正确,是因为很多 Subversion 的导入处理时间都花在要处理的目录的重现上,所以创建单个文件反而可以大大节省时间。使用
Subversion 的高效签入脚本会导致难于接受的等待时间。该脚本之所以要花费那么多时间,是因为它实际上要将整个二进制文件的副本导出到本地磁盘,以进行比较。
这些研究只考虑不同的存储方法对向 Subversion 存储、访问和检索二进制文件所需时间的影响。我们仍然需要调查以不同存储格式存储二进制文件所需的大量服务器磁盘空间。
表 2 显示了很多将二进制文件存入 Subversion 的方法。它还显示分别使用 import
命令和高效签入脚本时在 Subversion 服务器上使用的磁盘空间。表 2 中的第 1 列描述当把二进制文件放到服务器中时,
Subversion 用户如何存储它们。第 2 列显示二进制文件在本地系统上的大小。最后两列显示二进制文件在服务器上的大小,首先使用
Subversion import
命令,然后使用 Subversion 高效签入脚本。
同样,我们收集大量结果,以确定结论,但是这里只展示一个有代表性的例子。
表 2. 不同方法花费的输入和输出时间
本地存储格式 |
本地大小(Mb) |
服务器上的大小(Mb) |
导入 |
高效签入 |
目录 |
285 |
128 |
61 |
Tar 文件 |
219 |
103 |
102 |
压缩的 tar 文件 |
75 |
75 |
75 |
空间测试结果
表 2 表明,在服务器空间方面,当使用 import
命令时,空间效率最高的方法是以单个压缩文件的形式存储二进制文件。这种方法使用的空间大约是单个未压缩文件所占空间的
75%,大约是以常规目录结构形式导入二进制文件时所使用的空间的 60%。不过,使用高效签入方法可以得到更好的结果。高效签入一个目录结构所用的空间少于导入常规目录结构时所使用的空间的
50%。也就是说,与导入相比,以单个未压缩文件形式高效签入二进制文件只能少用少许空间,而以压缩的 tar 文件的形式签入二进制文件则根本不能节省空间。
这些结果表明,Subversion 自有的压缩算法在压缩二进制文件方面略强于使用本地压缩文件的 gzip
命令。还有一点也很明显,Subversion 不能压缩已经压缩过的文件。也许最有趣的是,在 Subversion 中存储一组二进制文件的空间效率最高的方法是在常规目录结构上使用高效签入。
接下来,我们调查不同服务器认证方法对将二进制文件移入和移出 Subversion 所需时间的影响。表 3 显示了 Subversion
服务器上的多种认证方法。对于每种方法,我们分别测出以完整目录结构形式、以未压缩 tar 文件形式和以压缩的 tar 文件形式导入二进制文件所花的时间。下面展示了这些认证方法(注意,这些方法是递增的,所以
“ldap_group” 包括 “no_path_auth disabled” 和 “Basic” 的设置):
- No auth 只使用文件系统认证,在本地访问。
- Basic 意味着使用 HTTP 通过 Apache Web 服务器访问 Subversion。
- no_path_auth disabled 意味着大量路径处理被关闭。
- ldap_group 意味着设置并使用 LDAP 组。
- ssl 使用 HTTPS 协议。
表 3 提供了一个代表性的例子。
表 3. 不同认证方法所需的输入时间
认证方法 |
目录 |
tar 文件 |
压缩的 tar 文件 |
No auth |
29m 25s |
2m 20s |
1m 17s |
Basic |
44m 23s |
2m 51s |
1m 25s |
no_path_auth disabled |
44m 28s |
2m 53s |
1m 24s |
ldap_group |
45m 21s |
2m 53s |
1m 24s |
ssl |
45m 27s |
2m 52s |
1m 25s |
认证测试结果
如表 3 所示,如果在 Subversion 服务器上不进行认证,则可以取得最快的导入时间。然而,在大多数情况下,总需要某种形式的认证。我们发现,使用的认证方法对将二进制文件移入和移出
Subversion 所需的时间影响不大。
我们想要确定,在解决 Subversion 性能问题时,是否需要重点考虑硬件。为进行这个测试,我们将 Subversion
服务器宿主在各种不同的机器上,并比较将二进制文件导入每种机器上的 Subversion 服务器所需的时间。由于可用的机器类型多不胜数,我们将调查局限于更常规的考虑,如表
4 所示。注意,Desktop 1 是一台共享机器,这意味着除了宿主 Subversion 储存库之外,它还被用于其它任务。Desktop
2 是一台专用机器,只用于 Subversion 储存库。
表 4. 不同机器对应的输入时间
机器类型 |
机器规格 |
时间 |
Desktop 1,共享 |
CPU: 2x500MHz PIII, RAM: 500Mb |
28m |
Desktop 2,专用 |
1x3200MHz P4, RAM: 2000Mb |
2m |
Server,共享 |
0.2 CPUs |
28m 0s |
Server,共享 |
1 CPU |
13m 19s |
Server,共享 |
2 CPUs |
13m 19s |
硬件测试结果
表 4 中的结果表明,用于运行 Subversion 服务器的机器对于导入二进制文件所需时间有巨大的影响。比较两台台式机,专用的、强大的
Desktop 2 比共享的、处理能力较弱的 Desktop 1 快 14 倍。实际上,这台专用台式机甚至比大型服务器还要快得多,不过增加服务器的
CPU 处理能力可以使导入速度快上一倍。
显然,为了减少将二进制文件移入和移出 Subversion 所需的时间,选择适当的机器非常重要。
这项调查的发现只适用于被调查的特定系统,所以这里显示的实际值对于其它系统可能意义不大。而模式才是更重要的,因为它们将在任何
Subversion 系统中被复制。根据我们的调查,当将一组二进制文件存储到 Subversion 中时:
- 时间效率最高的方法是创建一个单独的、压缩的、包含二进制的文件。
- 空间效率最高的方法是在常规目录结构上使用 Subversion 的高效签入脚本。
- 在 Subversion 服务器上使用任何形式的认证都将损失性能。
- 使用专用的、处理能力强的机器来运行 Subversion 效果最佳。
通常来讲,这些结论可以作为存储和检索二进制文件时优化 Subversion 性能的一个框架。但是,基于以下考虑,这些结论变得复杂起来:
- 对硬件的调查只适用于被调查的特定系统。与很多项目使用的二进制文件相比,测试系统中使用的二进制文件非常大。我们调查的模式仍然适用,但是使用范围要小一些。由于其中一些结论处理时差异较大,需要根据调查中的结论来制定明智的决策。
- 对认证方法的调查是使用不同认证方法时比较将二进制文件移入 Subversion 所需的时间。这个度量对于被测试的系统来说是最重要的,但是实际上认证方法对文件移入
Subversion 这个过程的影响很小。诸如
svn log
之类的访问很多路径的命令对认证方法的依赖则强得多。因而值得注意的是,虽然认证方法的选择对于提高二进制文件输入性能并不是特别重要,但是在其它领域可能比较重要。
- 使用高效签入脚本的好处还取决于项目的性质。使用高效签入时, Subversion 服务器上所需的很多空间在很大程度上取决于签入的每个版本之间有多大的差异。如果各个版本之间的差异较小(例如所测试的开发系统),则高效签入的空间效率则会大大增加。
- 值得怀疑的是,如果将一个目录结构组合成单个的文件,不管压缩与否,是否对于每个系统都可行呢?这种方法的一个缺陷是,它为在大多数环境中浏览二进制文件造成了不便。而且不便于直接在
Subversion 中处理二进制文件。在修改二进制文件之前,必须从 Subversion 中移出二进制文件,然后将它转换成原有的格式。在某些情况下,这些问题将排除目录方法,或者使之与被考虑的系统无关。
本文中的性能结论广泛适用于大多数使用 Subversion 存储和检索二进制文件的系统。但是,如何优化 Subversion
的决策必须以给定系统的环境和资源为基础。例如,拿被测试的系统来说,时间要远远优先于服务器空间。因此,在将二进制文件导入 Subversion
或从中导出它们之前,可以将二进制文件存储为压缩的 tar 文件。压缩二进制文件可以使等待时间最短,因而符合项目需求。服务器空间的使用对系统的影响可以忽略不计,在任何情况下,与使用高效签入相比,压缩的
tar 文件只占用略微多一点的空间。
如果只考虑时间,那么使用快速的专用机器,结合最小的二进制文件的压缩 tar 文件,可能是最理想的优化。禁用认证可以节省更多的时间,但是大多数系统都要求认证。认证方法的选择对存储和检索二进制文件所需的时间影响不大。
如果只考虑服务器空间,那么在常规目录结构上使用高效签入这种方法将占用最少的空间。如果二进制文件各个版本之间的差异很小,那么这种方法就更加有益。在包含大型二进制文件的系统中,时间因素很难影响这种方法成为最佳解决方案。
在很多系统中,可以采取折中的方法。如果时间很重要,则尽量导入单个的压缩文件。这样便于尽快将文件放入 Subversion
中,同时也便于其他人快速从 Subversion 中导出该文件。然而,如果速度不是问题,那么可以采用高效签入。如果二进制文件用得不多,但是必须存储起来,以防将来需要,那么这种方法就很有效。
如果知道如何有效地将二进制文件存储到 Subversion 中,就可以节省小组成员数百个小时的时间和以千兆计的服务器空间。根据系统的细节和需求做出明智的决定,这是最可取的方法。本文应该可以帮助有类似需求的用户和系统管理员。
学习
获得产品和技术
讨论