基于虚拟机并使用 Vagrant(译注:Vagrant用于创建和部署自动化虚拟化开发环境)开发环境主要瓶颈是文件系统的性能。各平台的CPU区别是很小的,甚至可以忽略不计,而且RAM只有在很多虚拟机(译注:指同一台物理机上的虚拟机)都活跃时才会成为性能瓶颈。昨天我花了大部分时间测试并分析了通用的文件系统机制,现在把我结果分享给大家。
我将以对结果的分析开始,因为这是绝大部分人最感兴趣的部分。其他诸如具体测试方法、使用的软件、我所得到结果的原始数据等可以在分析的后面看到。
在下面呈现的每一个图表中,我们以不同的方式测试读写一个文件。对于每一个图表,写入文件总大小是固定的。Y轴是以KB/s为单位的吞吐率,X轴是“记录大小”或者一次性被读/写的大块数据大小,以KB为单位。
不同的测试环境如下:本地、VirtualBox本地、VMware本地、VirtualBox共享文件夹(vboxsf)、VMware共享文件夹(vmhgfs)、NFS。”本地“是指用测试环境中自己的文件系统。”本地“是在宿主机器上,” VirtualBox本地“是在VirtualBox虚拟机跟设备上,诸如此类。NFS只在VirtualBox上进行测试,因为VirtualBox和VMware的性能特点应该很相近。
对于所有图标,吞吐率(Y轴)越高越好。
小文件的顺序读取
首先,是一个对64KB文件的串行读取操作,测试了读取各种记录大小。在真实环境中对小文件进行串行读取的操作一般有运行时加载应用程序的源码,编译,或者测试。
第一件你注意到的但无力改变的事情莫过于,NFS对于小文件的读取性能简直无法相信。NFS性能很强悍很可能是因为由于大量预读和缓存操作。我对于NFS性能比本地虚拟文件系统好没有很好地理论解释。
这里的VMware共享文件夹正好可以干掉VirtualBox共享文件夹。VirtualBox共享文件夹的读取性能简直糟透了。如果你看过原始数据,你会发现吞吐率从没超过100MB/s,然后VMware从没低于500MB/s,甚至高峰时是900MB/s。
有意思的是,有时候虚拟中的本地文件系统性能竟然比宿主机的好。这个测试用的是原始不带用户空间缓存的read()系统调用。很可能虚拟机管理器会为虚拟机的读操作进行提前缓存,所以它们的性能会比需要进行上下文交换的宿主机操作系统内核要好。以上理论也可以从调用fread()的基准测试程序的原始数据中得出。在那些测试中,宿主机的本地文件系统每次都能打扮虚拟机的文件系统(译注:fread()和read()的很大不同之一是,前者带缓冲,后者不带缓冲,因此这里如果都有缓冲,显然本地文件系统性能要好)。
大文件的随机读取
这里测试随机从64MB文件读取任意大小的块的吞吐量,和上面一样是读取各种记录大小。这个文件是之前测试文件的1000倍。这种类型的操作可以在处理数据库的读请求时见到。
对比上一个针对小文件串行读取的试验,VMware共享文件夹和VirtualBox共享文件夹的性能差别变得非常大。VirtualBox表现得十分差,以至于你都不容易在上图中看到它。再一次地,VirtualBox的吞吐量从没超过100MB/s,另一方面,VMware的峰值却是7GB/s。因为VirtualBox的吞吐量在各种测试中基本没差别,我推断在VirtualBox共享文件夹系统里有一个代码热路径限制了其性能,很明显VirtualBox有地方做的不对。
NFS变得没有之前的试验突出了,很可能因为它的预读取在该测试里受益有限。尽管如此,相比其他选择,NFS仍然表现得非常好。
但是,就像之前的实验一样,我们仍然能发现在虚拟机里的性能比宿主机的要好,这还是因为虚拟机管理器会很聪明的做缓存操作,然而宿主机的原始的系统调用是不会允许这种事情发生的。
小文件串行写
让我们看看针对小文件的串行写操作。这种情况很精确的描述了存储段状态、临时文件,或者编写新的源代码文件。
第一个值得注意的事情是,针对这种写操作NFS性能变得十分差。这里可没有供NFS做的缓存操作,所以你必须支付因为网络开销带来的代价,以及在宿主机那里再写到磁盘,最后还要等待VM(虚拟机)写操作成功信号。天哪!
各种”本地“文件系统表现得都非常好,又一次虚拟机打败了宿主机,再一次,这还是因为虚拟机管理器的缓存操作。
共享文件系统表现相近,但是本次试验的VirtualBox明显地击败了VMware。
大文件随机写
我们要看的最后一张表是测试随机写一个大文件(64MB)。就像我们的大文件随机读测试一样,这是一个针对数据库如何表现的很好地测试。
这里真的和小文件串行写的实验差不多,因为这里测试的是大文件,所以不同测试之间的区别会大一些,但是除此之外,结果基本上一样。
NFS在写的时候表现依然糟糕。VirtualBox共享文件夹在写操作上继续打败VMware,并且虚拟机管理器性能还是比宿主机好。
虚拟机管理器表现得比宿主机好是我最感兴趣的地方。测试结果明显的标示,虚拟机管理器一定是谎称同步写(译注:而非真实同步写)。这也就证实了我用Packer看到的,如果虚拟机没有被正确的关闭,你提交的那些写操作就会丢失。虚拟机的fsync()调用不是表示数据被写到了宿主机硬盘上,只是将写操作提交给了虚拟机管理器。
整体分析
置于共享文件系统,VMware有你想要的虚拟机管理器。加载web页面,运行测试用例,编译软件等都属于繁重读操作。VMware共享文件夹的读性能会干掉VirtualBox,尽管VirtualBox共享文件夹的写性能稍微比VMware好一点。
如果你可以选择使用NFS,那么就用NFS。再次强调,读性能要比写性能有价值的多。
虚拟机管理器读/写性能都很出色(因为它作弊)。由于以上数据,我肯定会专注于Vagrant新的只用本地文件系统的同步文件夹实现(例如rsync,或者用本地文件系统作为NFS客户端而不是服务端)。
更直接地:如果你用虚拟机进行开发,如果可能的话,把数据库文件移出共享文件系统。你会看到很大的性能提升。
最后,我不认为以上结果有令人非常惊讶的地方,自从2010年后,Vagrant已经支持NFS同步文件夹,因为我们很早就意识到共享文件夹的性能很差。但是,用一些数据去标示不同的行为是值得做的,并且,这也为每一个系统在做什么提供了一些有意思的见解。
测试软件,配置,原始数据
宿主机是一个2012年的Retina MacBook Pro,硬盘256G SSD,运行Mac OS X10.9.1操作系统,这里标示成本地。
VirtualBox版本是4.3.4,运行Ubuntu12.04虚拟机,其中安装并使用了VirtualBox客户插件。测试中的VirtualBox的跟设备被格式化城ext3文件系统。在跟设备上的测试被标示成VirtualBox本地。然而在共享文件系统(vboxsf)上的测试被标示成VirtualBox共享文件夹(vboxsf)。
VMware Fusion版本是6.0.2运行Ubuntu12.04,其中安装并使用了VMware Tools 5.0。测试中VMware中的跟设备被格式化城ext3文件系统。在跟设备上的测试被标示成VMware本地。然而在共享文件系统(vmhgfs)上的测试被标示成VMware共享文件夹(vmhgfs)。
NFS服务器是OS X 10.0.1附带并构建的。NFS客户端来自于Ubuntu12.04中的nfs-common安装包,在UDP之上采用NFS协议3,在NFS上的测试被标示成NFS in VirtualBox。
基准测试软件是 Iozone Filesystem Benchmark 从用于64位linux的源码中编译而来。同样的二进制被用于每一个测试场景,除了本地测试是用的一个从源码编译而来的lozone 32位OS X二进制。Lozone的参数是-Racb。
除了以上提及的,剩余的设置和没提到的都是默认或者没有用到。
以上测试的原始数据可以在这个 Excel workbook 中获取。还有很多其他图标在这个 imgur album 中。