细说硬件虚拟化(二) - 译言翻译

来源:百度文库 编辑:神马文学网 时间:2024/04/29 11:13:41
硬件加速的虚拟化:Intel VT-x和AMD SVM
你是不是觉得硬件加速的虚拟化技术,可以从根本上把上述的那些性能损失降至最低?不幸的是,情况不是这个样子的。硬件加速的虚拟化并非是经改进了的二进制改编,或者泛虚拟化技术的一个新版本。恰恰相反的是,硬件加速的虚拟化技术的出现,本身只是为了弥补x86指令结构不能被(有效)虚拟化的缺陷。这意味着硬件加速虚拟化还是沿用了以前的思路,它通过一个“VMexit”的机制来强制实现从客户操作系统切换到VMM,来捕获所有发生的中断和特权指令。你可以将这样一种技术看作是IBM S/370虚拟技术的一个改进版。
硬件加速虚拟化的一个优势是,客户操作系统可以运行在它想要的特权级别上(ring0级),而VMM则运行在一个新的有着更大特权的级别上(Ring-1,或者“根模式”)。只要系统调用没有涉及到关键指令,那么VMM就不会再截获这样的系统调用,客户操作系统也就可以直接为用户应用程序提供核心服务了。这是硬件加速虚拟化所带来的一个很大的改进。
(原文有图示,我试着把相关的图片发上来,但没有成功。惭愧!)
在硬件加速的虚拟化技术中,客户操作系统运行在它本来的级别上:ring0
而现在的问题是,——尽管这样的虚拟化已经是在硬件的级别上实现了,每一次从VM(虚拟机)到VMM(虚拟机监控器)的切换都要一定的(往往是大量的)CPU时钟周期。具体需要多少CPU时钟周期依赖于CPU的架构如何,和不同的操作(VMexit,VMexit,VMread等),这些可以花费从百来个CPU时钟周期到上千个时钟周期不等。
由此看来在硬件加速的虚拟化里,从VM到VMM的往返路程并非是桩轻松的差事。当Intel VT-x或者AMD SVM(又或AMD-V)不得不处理那些如同系统调用这样的复杂的指令时,——这些指令通常要求消耗大量的CPU时钟周期,那么Vmexit/Vmentry之间的切换所带来的附加开销就变得微不足道了。但是,如果VMM要截获并加以模拟的操作是如此的简单,那么这切换来切换去的操作所带来的开销就反而变得得不偿失了。
创建进程、上下文环境切换、小面积页表更新等这样相对简单的操作在原生系统上只需几个时钟周期,所以“到VMM间的来回切换”所需要的时间就是在浪费大量的时钟周期了(和原生没有经过虚拟化的系统相比)。而如果是使用二进制改编,改编器所做的仅仅是用经改编后增加了长度的代码来替换原来的代码,以便VMM进行处理。对于泛虚拟化来说,情况也是这样,和硬件加速虚拟化相比,在处理这些简单操作时,它的速度要快得多。
(原文图示)
至强的变迁使得进入VMM和离开VMM的延迟越来越低
在解决这个问题的过程中,Intel和AMD第一步要做的是降低这些VT-x指令所需要的时钟周期。举例来说,VMentry这个指令在早期的至强Paxvile和至强70xx上需要634个时钟周期,而到了Woodcrest(至强51xx)、Clovertown(至强53xx)和Tigerton(至强73xx)同样的指令就只需要352个时钟周期。从上面的图示,你可以看到,在2005年里VT-x指令的第一代实现中,速度的表现真可谓是差强人意。在最新的至强54xx(“Harpertown”)上,对那些最重要的指令VMM延迟已降到原来的12%-25%之间,就那些平常少用到的指令其优化上限更是达到了75%。我们将会在下文里给出几组有关的精确的数字。
(原文图示)
不同的Intel处理器家庭其进出VMM的延迟(纳秒)是不同的
它们第二步可以做的是减少VMM事件的发生频率。说到底,虚拟化所带来的整个的额外开销,就等于这些事件的发生频率乘以每个事件所消耗的时间。这样我们就得到下面的这个公式:
总体开销=事件1×延迟1+事件2×延迟2……事件n×延迟n
这里,虚拟机控制块,——位于内存中类似于表的数据块(缓存),是VT-x和AMD SVM的一部分,也体现了它的价值。它为每个客户操作系统缓存了它们的虚拟CPU的状态信息。它的存在,可以使客户操作系统在没有VMM的干预之下具有直接运行的能力。根据这个控制块里的控制状态的不同,VMM能够让客户操作系统自行处理一些有关的事件:中断或者处理一些页表的更新工作,及其它一些硬件管理工作等。VMM根据需要配置虚拟机控制块,在某些场合下,它能够让客户操作系统交出控制权,而在另一种情况时VMM可以客户操作系统继续得以运行。如此一来,就有可能减少CPU强制停止客户操作系统运行的情况(VMeit)的发生,——当客户操作系统交出控制权时,CPU会切回到VMX根模式(ring-1)状态,VMM就取得了控制权。
第二代硬件加速虚拟化技术:Intel的EPT和AMD的NPT
就象我们在“内存管理”中所讨论的一样,为不同的客户操作系统管理虚拟内存,并把它们翻译到对应的物理内存页是一件很费CPU的工作。
(这里原文也有图示的)
如果没有影子页面,我们不得不将虚拟内存(蓝色)翻译到“客户操作所管理的物理内存”(灰色),然后再把后者翻译为真正的物理内存(绿色)地址。幸运的是,“影子页面”技术精减了繁琐的翻译过程,它成功地跳过了“客户操作系统所管理的物理内存”这个中间环节,使MMU(内存管理单元)直接把(用蓝色表示的客户操作系统的)虚拟内存翻译到真正的物理内存页表上。当然这里还有一项免不了工作要做,当每一次客户操作系统的页表数据发生更新时,把这样的更新记录在“影子页页表”中。这对于软件实现的虚拟化技术(包括二进制改编和泛虚拟化)的性能来说是个不小的影响,而对于早期的硬件加速虚拟化技术的影响则更是灾难性的。而原因就在于,你为此必须面对很多性能开销很大的VMentry和VMexit调用。
新一代硬件虚拟化技术,像AMD的嵌套分页技术和Intel的EPT技术,使用了并不优雅的硬件技术部分地解决了这个问题。
(原文图示)
EPT和嵌套分页使用了一个“超级”TLB缓存来同时追踪客户操作系统和VMM的内存管理情况
如上图所示,一个有着嵌套分页支持的硬件虚拟化的CPU,在它的TLB里同时缓存了(客户操作系统的)虚拟内存到(客户操作系统的)“物理内存”,以及(客户操作系统的)“物理内存”到真正的物理内存地址的转换。这个TLB有一个新的VM专用的标识符,称之为地址空间标识符。它允许一个虚拟机能够识别一条TLB数据到底是属于哪个虚拟机的。由此,一个虚拟机工作状态的变换将不会刷新整个TLB缓存数据。不同的虚拟机所有的TLB数据都可以在这个缓存里和平共处,相安无事,当然前提是这个TLB拥有足够大的容量。
这样一来,VMM的工作就轻松许多了,再也用不着常常更新影子页面表数据了。考虑到这样的事实,虚拟机监控器总是会介入到每一次影子页面数据的更新中(一个运行中的虚拟机就会一个相应的影子页面表),那么很清楚嵌套分页技术将带来大幅的性能提高(依据AMD的说法性能提升的上限可以达到23%)。如果你的系统中每个虚拟机拥有超过一个的(虚拟)CPU,那么嵌套分页的技术就更显得重要了。多个CPU之间必须经常同步页面数据,其结果直接导致影子页面的更新将大量增加。就在你为每个虚拟机分配多个(虚拟)CPU的时候,由影子页面带来的性能损失将更为明显。而在使用了嵌套分页的系统中,就像在原生的系统里一样,多个CPU所要做的仅仅是让TLB缓存保持同步即可。
嵌套分页和EPT技术就只有一个弱点,如果在TLB缓存中没有正确的数据,那么从虚拟地址翻译到真实物理内存地址的工作将会变得非常复杂。在蓝色区域里我们所做的每一步,都必须在橙色区域里重新做一遍。所以,在“原生态”情况下4次的数据搜索量,到了这里就变成了16次(发生在蓝色区域里每一个动作,相应地在在橙色区域里会有4次这样的动作发生)。
为了尽量减少这种情况的出现,一个CPU就需要比以前大得多的TLB缓存容量,而如果发生一次TLB数据不中的情形,那么它的代价将是很大的。如果类似的情况发生在原生系统上(即没有虚拟化的情况下),我们所要做的是在系统的主存中进行4次的数据搜索,这对系统的性能也算是个小小的制约了。而在一个“拥有嵌套分页技术的虚拟客户操作系统”上发生这样的情况,我们将面对的是在“缓慢”的主内存中高达16次的数据搜索量,这对系统的性能来说将会是个灾难!幸运的是,如果TLB的容量足够大的话,那么就只有极少的软件会引起大量的TLB数据不中的情况。
迫在眉睫的标准化要求
因为AMD和Intel的各自为政,再一次出现了彼此互不兼容的x86的扩展集。它们的硬件虚拟化扩展技术没有走统一的标准化道路。这意味着软件开发者必须为Intel的VT-x和AMD的SVM开发不同的支持模块。Xen 3.0.2用了大约9500行,相当于整个代码库8%的代码量来同时支持这两种不同的技术。正是基于这样的原因,Xen VMM的体积增加了近4%之多,不过它还是在可以承受的范围之内。但愿今后这样的局面不会走到超出这个程度的那一天,毕竟AMD和Intel之间技术上的差异是如此之小,你因此怀疑再存在这两种不同的扩展集到底还有什么意义?
说到这里,让我们看看到底哪些CPU有了硬件虚拟化的能力?下面的表格列出了当前最重要的服务器CPU。
支持硬件虚拟化的CPU
处理器
硬件虚拟化类型
支持程度
Xeon 50xx, Xeon 70xxx and Xeon 71xx
支持硬件虚拟化(只支持HVT)
速度很慢
Opteron Socket-F, Xeon 53xx
支持硬件虚拟化(只支持HVT)
速度中等
Xeon 54xx
支持硬件虚拟化(只支持HVT)
较快
Nehalem, Quad-core Opteron
支持HVT和嵌套分页技术(EPT/NPT)
未知
这里需要指出的是,支持DDR的AMD皓龙8xx和2xx并不支持HVT;然而其速度和早期支持HVT的Intel的至强相比却要快很多。
基准测试
有关性能的问题在虚拟化技术的鼓吹者那里似乎不是一个十分紧要的问题,在各式各样的辞藻华丽的宣传手册里也没有关于这方面的具体细节。从很多已发表的基准测试数据来看也似乎给了这种冷漠以一个正当的理由:在当前处理能力极为强劲的4核CPU的时代,谁会为3到10个百分点的性能的损失而在意?事实上,ESX、Xen这样一些以虚拟机监控器或者VMM为基础的虚拟化技术表现得十分抢眼,尤其是在你把它们和那些基于宿主系统的方案比较的时候,——比如VMware和微软的Virtual Server 2005,就更是如此了。后者在一个宿主操作系统上实现它们的虚拟化层,这让它们的运行效率变得十分低下。
请看下面的图示[6],这里的基准测试数据是由剑桥大学测试完成的。这组基准测试是在原生的Linux和Xen,以及VMware Workstation和它上面的用户态模式的Linux之间完成的。后者就是一个基于宿主操作系统的虚拟化的例子,即它的虚拟化是运行一个宿主操作系统之上的。
(原文图示)
对很多商用应用程序来说基于宿主操作系统的虚拟化是个糟糕的方案
虚拟化技术厂商经常喜欢使用SPEC CPU 2000整数的基准测试数据。就如你所看到的,所有的虚拟化技术在该项测试上都有非常不错的成绩。根据这些数据,Xen的表现和原生操作系统一样的好。然而,当你开始一项内存要求很高的基准测试,比如编译Linux内核,你就可以清楚地看到,基于宿主操作系统的虚拟化技术的速度就开始落下去了。在OLTP和Web程序上的表现更是一落千丈。
SPEC CPU 2000之所以普遍被用于基准测试是它的道理的。它是一个主要测试CPU性能的测试软件,很少访问其它的硬件设备,在大多数时间里也没有太多的用到操作系统的核心功能。而且这里有一点也值得特别注意,那就是测试用的是“2000”这个版本。这是因为它的2006版占用的内存资源比较大,这有可能使它在虚拟化的场合里性能有较大的损失。
因此,有一点很清楚,SPEC CPU 2000在虚拟机上的整数性能并不能说明什么问题。和VMM不同,这一类的软件在它们的任务中没有VMM要面对和处理的复杂的情况。那么Specjbb2005又是什么情况呢?在虚拟化厂商的性能测试数字中,这是另一款经常出现的服务器基准测试软件。当然,这些数据或多或少道出了一定的真相,但是大多数Specjbb2005的基准测试数据都是在单个CPU上进行测试的,或者如果它们的测试环境是在一个多虚拟CPU的环境中进行的,测试时却只有一个虚拟机是处于活动状态的。但是在真实的环境中,这样的情形是非常少见的:你不会在你已经虚拟化了的服务器上,只运行一个虚拟机。
我们将在下一篇文章里给出我们详细的测试数据,这里我们大致浏览一下其中的一些数据。我们的服务器配置了四核的Xeon MP Intel SR6850HW4(4X3.2GHz双核Xeon 7130M,详细的配置请点击这里),我们是按照这里说的来配置Specjbb2005的。为了使我们的测试数据尽量避免不必要的波动,我们关闭了超线程功能。
虚拟化性能测试
虚拟机数目
每虚拟机CPU数
SUSE SLES 10
Xen 3.0.3
VMware ESX 3.0.2
1
1
1%
3%
1
4
3%
7%
4
2
5%
15%
4
4
7%
19%
这里,给我们性急的读者透露一点信息,我们也为最新的Xeon、Opteron以及虚拟监控器(包括;ESX 3.5等)准备了一份详尽的测试报道。我们知道就凭上面的几组数据并不会让你对虚拟化技术有个全面而清晰的感觉,它们的出现不是为了让你对这种技术有个理性的认识,而只是我们整个序列中的一道开宴前的开胃小菜而已。
但是,即便是上面几组稍显过时的数据还是很让人感兴趣的。如果你前面没有注意到过,那么所谓的“一虚拟机用一个CPU”的测试似乎就是在告诉你虚拟化并未带来任何的性能损失。如果眼下的CPU有个8个核心可用,那么一种更为现实的配置将会是4个虚拟机,而每个虚拟机都会有两个虚拟CPU可用。在这种情况下,性能的损失依然不是很大,然而已经是实实实在在的在那里了。
在上表的最后一行里(每个虚拟机有4个虚拟CPU),我们的测试负荷依然沿用了2-2-2-2配置里的负荷状况。在最高负荷时,我们也只开了8个线程。就算如此,平均的性能损失也是很大的。而且上面的表格说明的还不是全部的情况,请看下面的图示。
(这里原文也有图示的)
如果你为虚拟机分配的虚拟CPU数目超过了你实际拥有的数量,有一点你必须要知道的是,和一个物理的CPU对应一个虚拟CPU的情况相比,就算是在低负荷的情况下,虚拟化的性能也是很差的。
请不要误会我们的意思,当前的虚拟化产品在大多数情况下都能有良好的表现。但是,无论在哪一种情形底下,虚拟化都不会带来大幅的性能下降的这样一种印象也是不正确的。比方说,我们就曾经在一台强大的Xeon 5472的服务器上观测到,一个简单的OLTP sysbench负荷测试也会有超过20%的性能损失。在另一些场合下,我们甚至见到过性能损失在40%这样的例子。在眼下这种时候对这种现象妄加判断还为时过早,因为类似的测试还在不断地进行之中,我们相信更多的关于虚拟化性能方面的研究将会为我们带来期待中的答案。
结语
当我们第一次听说Intel的VT-x和AMD的SVM技术时,我们期望它们将会为软件虚拟化技术,比如二进制改编和泛虚拟化技术,带来性能上的提升。无论是AMD,还是Intel,都表现出新的技术将会使当前以纯软件为基础的虚拟化得到增强和提升的姿态。
事实上,AMD和Intel所做的是扩展x86架构,使“经典的虚拟化”在x86平台上成为可能,而这和老式的IBM大型机上所使用的虚拟化技术十分的相似。换句话说,硬件虚拟化并没有让二进制改编或者泛虚拟化技术得到增强,它走的是一条截然相反的技术路线。从性能的角度说,第一代硬件虚拟化技术甚至是一种倒退,但是它的出现也使得今后的发展成为可能。第一代的硬件虚拟化技术已经得到了改进,VMware利用这种技术现在已经可以支持64位的客户操作系统,同样的,Xen也可以用来运行未经修改过的操作系统了(就像Windows)。到目前为止,在软件虚拟化技术已经非常成熟且已成了当今虚拟化技术的标准的背景下,硬件虚拟化技术还有很长的路要走。
以VT-X+EPT和AMD-V+NPT(即嵌套页表)为代表的第二代硬件虚拟化技术改进不小,然而尽管它可以大幅提高系统的性能,但也因为TLB不中的高额代价也使它不能保证在每种场合下都能有如此良好的表现。换个角度来看,软件虚拟化技术已经非常成熟,但也正是如此,留给它可以改进的空间也已经很小了。最明智的办法应该是结合利用两种技术各自的长处,这正是VMware、Xen和Microsoft正在做的。
VMware ESX是这种趋势的最佳代表。针对最为关键的I/O设备,ESX使用了泛虚拟化的驱动(CPU除外),而对其它不是很重要的I/O设备则采起了模拟处理,用二进制改编来避免因“陷阱和模拟”所带来的高额性能损失,再利用了硬件虚拟化技术来支持64位客户操作系统的能力。以这种方式,虚拟化的应用程序性能获得了很大的提高,在一些场合下甚至和原生态下相差无几(有没有VMM的存在对性能影响不大)。
这当然不是说性能已经不是什么问题了。在VMWorld 2008会议上,这么多人的有关性能的专场报道,以及我们自己(先前)搞的基准测试,都表明在现实世界里,尽管有多核处理器强大的处理能力,虚拟服务器的性能一直是个有趣而富有挑战性的问题。如果你运行的一直是CPU密集型的程序,那么性能就不是个问题,——因为程序的指令是直接运行在处理器上的。然而,请考虑一下如果有如下一个或几个特征的程序出现在虚拟化环境中,情况会不会有所不同。
程序有高频率的系统调用或者中断
频繁地访问内存(DMA)
程序需要大量访问I/O设备
程序要求有SMP(Symmetrical Multi-Processin,对称多处理技术)的支持才能发挥良好的性能
像这样的程序在虚拟服务器上要获得良好的性能,要注意的地方有很多。现在,到了该进一步探讨基准测试的时候了,敬请关注我们的下一篇文章……
参考文献
[1]Robin/Irvine,2000年第9届USENIX安全年会报告,“关于奔腾处理器是否可以满足VMM的安全要求的分析”
http://www.usenix.org/events/sec00/full_papers/robin/robin_html/index.html
[2]Scott Devine,VMware的联合创始人及首席工程师,“虚拟机简介”。
[3]VMware的Ole Agesen,VMwareWorld 2008,“影响x86架构平台虚拟化性能的方方面面”。
[4] Keith Adams,Ole Agesen,VMware公司,“x86平台上软件虚拟化与硬件虚拟技术之比较”。
[5] Daniel P.Bovet,Marco Cesati,“理解Linxu内核(第三版)”,O’Reilly。
书号2005,ISBN: 0-596-0056502,第1.6节。
[6]Paul Barham,Boris Dragovic,Keir Fraser,Steven Hand,Tim Harris,Alex Ho,Rolf Neugebauer,Ian Pratt,Andrew Wareld,剑桥大学计算机实验室,“Xen和虚拟化的艺术”。