• 回答 (1)
  • 关注 (0)
  • 查看 (285)

在实验室环境中, 通过sysbench工具测试,虚拟机上的内存性能指标只有其物理机的一半左右:

测试命令:sysbench --test=memory run

ywojb10Tywojb10T提问于
龙珠粉丝255学生回答于
推荐

回答来自于问答智囊团成员:curuwang

专栏:https://cloud.tencent.com/developer/user/2177340

先说结论:测试工具和环境差异造成,实际性能并无差异

问题推导

理论上是否可能存在这么大的差异?

现代CPU的内存管理功能中有硬件辅助虚拟化技术,比如Intel的EPT(扩展页表)。在内存分配阶段,虚拟机的缺页异常会引发VM exit到宿主机,在宿主机上实际分配内存并建立EPT页表,这里确实会有一些额外的开销。然而内存分配完毕之后,虚拟机访问内存时,会直接通过硬件支持实现虚拟地址到宿主机物理地址的转换,并且还可以利用TLB实现虚拟地址到最终物理地址的转换加速,与只使用物理机环境并无额外的开销。

ept

通常的内存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

虚拟机的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函数的实现:

image.png

sysbench调用clock_gettime的方式为clock_gettime(CLOCK_MONOTONIC, tsp)。于是顺着如下调用链:

 __vdso_clock_gettime -> do_monotonic -> vgetsns

我们再来看vgetns的实现:

image.png

从vgetns我们可知,clock_gettime最终会根据不同的时钟源调用不同的vread函数。

尝试将虚拟机的时钟源调整为tsc:

 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

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,得到的数据和物理机一致,至此问题解决。

总结

  1. 借助硬件辅助虚拟化技术,物理机与其上的虚拟机内存读写性能几乎没差异
  2. 发现性能差异,先根据理论做一个最初假设推断。
  3. 针对“不符合预期”的性能差异,可以通过perf/strace等工具深入分析性能表现。
  4. 分析性能问题首要条件是保证环境一致,若环境不一致,那么可以从环境的差异性来入手分析可能导致性能差异的原因。

文章来源:腾讯云服务器专家服务团队,转载请注明出处。

回答过的其他问题

智能网优如何提升手游用户游戏体验?

据我所知,智能网优也提供非常精准的测试服务,在全国所有的省份所有的运营商都有部署一个测试节点,测试用户到骨干网最边缘节点的速度是多少,也对到路由器网关进行测试,以及到游戏服务器进行测试,得出每段网络的延时分别是多少。

对于直播答题类APP的欺诈违法行为目前都采取了哪些应对措施?

在直播答题火爆网络以后引来了形形色色的“垃圾内容”,在答题时出现了许多涉黄涉政等敏感词刷屏,脏话,甚至机器恶意刷屏等等低俗的垃圾弹幕,甚至有人用用户昵称,用户头像设置涉黄涉政的敏感词,这位直播答题平台的监管带来了很大压力。不过针对此类问题,众平台纷纷采取了操作,在后台针对色情,涉...... 展开详请

如何搭建小程序音视频?

小程序账号怎么填写?

……你不说是那块的问题,截图和链接都没有,还指望别人给你解决问题?

如何使用Docker / Kubernetes建模PostgreSQL故障转移群集?

你可以给PostDock一试,无论是与搬运工,撰写或Kubernetes。目前我已经在我们的项目中使用docker-compose进行了尝试,其架构如下所示: pgmaster (primary node1) --| |- pgslave1 (node2) --|...... 展开详请

依赖性问题“SpringBootServletInitializer无法解析为类型”

不要做任何新事只需按Ctrl+ Shift+ o它会为你的项目添加正确的导入

关于作者

扫码关注云+社区

领取腾讯云代金券