背景
有小伙伴反馈在其实验室环境中, 通过sysbench工具测试,虚拟机上的内存性能指标只有其物理机的一半左右:
测试命令:sysbench --test=memory run
先说结论:测试工具和环境差异造成,实际性能并无差异
问题推导
理论上是否可能存在这么大的差异?
现代CPU的内存管理功能中有硬件辅助虚拟化技术,比如Intel的EPT(扩展页表)。在内存分配阶段,虚拟机的缺页异常会引发VM exit到宿主机,在宿主机上实际分配内存并建立EPT页表,这里确实会有一些额外的开销。然而内存分配完毕之后,虚拟机访问内存时,会直接通过硬件支持实现虚拟地址到宿主机物理地址的转换,并且还可以利用TLB实现虚拟地址到最终物理地址的转换加速,与只使用物理机环境并无额外的开销。
通常的内存benchmark工具,都是预先分配一块内存之后反复读写,这种情况下,理论上虚拟机和物理机的内存读写性能是没有差异的。
理论上没这么大差距的话,那可能是什么原因导致的差异?
理论上虚拟机和物理机在已分配内存后读写性能几乎无差别,那么差异就可能产生在两个地方:工具问题或者是OS问题。
我们首先从工具入手,业界对于内存基准性能测试使用比较多的是stream。编译好同一个stream二进制,分别在物理机和虚拟机执行,得到的数据是相同的:不存在所谓的性能差异。
那么问题缩小到sysbench这个工具本身在不同环境执行的差异上了。
sysbench数据差异原因分析
sysbench版本:1.0.20
测试命令:sysbench --test=memory run
某业务物理机测试数据:4158.16 MiB/sec
某业务虚拟机测试数据: 2850.51 MiB/sec
在执行sysbench命令时,我们使用perf top -p xxx
命令查看热点函数堆栈:
物理机的perf输出:
虚拟机的perf输出:
从top输出可以很清晰地看到,虚拟机上的clock_gettime和vdso_clock_gettime函数的cpu占比高了50%左右(55.40% vs 34.72%),cpu消耗了更多的时间在这些函数执行上,只有更少的时间在真正的内存读写操作,所以得到的数据偏低。
那么,是什么原因导致了__vdso_clock_gettime的性能差异呢?
首先弄清楚什么是 vdso, vDSO(virtual dynamic shared object),是内核提供的一种加速机制,可以让用户态程序不通过系统调用而能执行内核里的函数,在进程加载时,自动加入进程的地址空间。简单地说,就是内核提供了一个简单的函数库给用户态程序使用。
我们来看看centos 7.4的3.10.0-693.el7内核版本中的__vdso_clock_gettime函数的实现:
sysbench调用clock_gettime的方式为clock_gettime(CLOCK_MONOTONIC, tsp)。于是顺着如下调用链:
代码语言:txt复制 __vdso_clock_gettime -> do_monotonic -> vgetsns
我们再来看vgetns的实现:
从vgetns我们可知,clock_gettime最终会根据不同的时钟源调用不同的vread函数。
尝试将虚拟机的时钟源调整为tsc:
代码语言:txt复制 echo tsc > /sys/devices/system/clocksource/clocksource0/current_clocksource
之后再执行sysbench, 发现指标效果有了很大提升(从2850.51 MiB/sec到4134.65 MiB/sec),如此可以确定是虚拟机里面的vread_pvclock性能问题导致的结果差异。
实际上,通过代码查找,我们发现linux内核4.5版本已经对pvclock的代码做了优化https://github.com/torvalds/linux/commit/6b078f5de7fc0851af4102493c7b5bb07e49c4cb
代码语言:txt复制Before, vclock_gettime using kvm-clock took about 45ns on my
machine. With this change, it takes 29ns, which is almost as
fast as the pure TSC implementation.
该优化也被redhat backport到了3.10.0-862版本中(对应centos 7.5版本)。
将虚拟机的内核版本升级到3.10.0-862.el7之后,再执行sysbench,得到的数据和物理机一致,至此问题解决。
总结
- 借助硬件辅助虚拟化技术,物理机与其上的虚拟机内存读写性能几乎没差异
- 发现性能差异,先根据理论做一个最初假设推断。
- 针对“不符合预期”的性能差异,可以通过perf/strace等工具深入分析性能表现。
- 分析性能问题首要条件是保证环境一致,若环境不一致,那么可以从环境的差异性来入手分析可能导致性能差异的原因。
文章来源:腾讯云服务器专家服务团队,转载请注明出处。