虚拟化环境下Windows IO性能的解析是怎样的

48次阅读
没有评论

共计 4412 个字符,预计需要花费 12 分钟才能阅读完成。

本篇文章给大家分享的是有关虚拟化环境下 Windows IO 性能的解析是怎样的,丸趣 TV 小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着丸趣 TV 小编一起来看看吧。

前言
随着云计算技术与服务的发展和进步,越来越多的客户选择将业务部署到云端。但由于引入了虚拟化层,在业务部署过程中经常会遇到 IO 问题,通常也不易调试。下面主要介绍利用 perf、systemtap 等工具,帮助一位托管云客户调试 IO 性能问题,来分析虚拟环境下 Windows IO 的性能。

问题出现
有一次,托管云客户自己搭建了虚拟化环境,在同一台宿主机上创建 windows 2008 R2 和 Centos6.5 虚拟机,用 fio 分别测试其随机读性能,windows 2008 R2 的 IOPS 大约在 18K,而 Linux 的 IOPS 却可以达到 100K 左右。
• 客户测试用的 fio 配置
[global]
ioengine=windowsaio
direct=1
iodepth=64
thread=1
size=20g
numjobs=1
[4k]
bs=4k
filename=d:test.img
rw=randread
测试结果

win_fio1
• 云主机 IO 栈

io stack
云主机环境下,整个 IO 栈相对较长,涉及到 Guest OS 中的应用层 / 文件系统 /Block 层以及驱动层,虚拟化层,宿主机 OS 文件系统 /Block 层以及驱动层。因为涉及面多,所以其中任何一个环节出现问题都会造成性能下降,也为做 IO 的 Tracing 增加了难度。

从这次得到的信息来看,首先排除了宿主机文件系统和 Block 层以及驱动层的问题,因为同样情况的配置,Linux 系统并没有问题。
所以目前主要集中于两点
•Guest OS(Windows 系统)
•fio 程序
•文件系统 /Block layer
•VirtIO Block 驱动 虚拟机为 Guest OS 提供的是 Virtio Block 设备
•QEMU

如何排除 QEMU 的嫌疑?
对于 IOPS 的性能问题,很容易想到两种可能性:
•IO 延时过高
•设备支持 IO 队列太短

在队列的问题方面,Linux 和 Windows 虚拟机对应的 Virtio Block 设备都是一样的,那么就需要确认延时问题。

QEMU 完成 Block IO 花了多长时间?
幸运的是,Stefan Hajnoczi 已经为 QEMU 添加了 Tracing 的特性,因此可以很方便的统计出 QEMU 从接收到一个 IO 请求到完成所用的具体时长。

从上述统计来看,平均 IO 完成时间在 130us,由此暂时排除 QEMU 层造成太高延时的影响。另外,如果关注这种动态 Tracing 的 overhead,从测试观察上大致接近 20%。
排除队列和延时问题,可能造成影响的也只有 Guest OS 了。
•VirtIO Block 驱动的问题?
至少更新到最新稳定版本的 Virtio-Win 驱动,仍然存在同样的问题。
•Windows 文件系统 /Block 层的问题?
原生 Windows 系统在确认后并没有做任何配置上的修改。
fio 测试程序的问题

为什么 Linux 上 fio 没有问题呢?

两种可能性
在性能排查过程中,总是很容易陷入死局,经常会问到底是哪儿出了问题?因此一切可能影响的因素似乎都没有做任何变动。从经验来看,大部分性能问题都可以分成两种可能:
•on cpu
•off cpu
重新来看这个问题,在基本排除 IO 延时问题后,对应的问题还有两种可能性:
•CPU 极其忙碌,但是大部分时间并不是在做 IO 处理;
•CPU 经常处于空闲状态,那相应的也没有主要在处理 IO。
注:之所以说到目前为止并不能排除 IO 延时的影响,是因为只排除了 QEMU Block 层可能的影响,但是还有 Guest OS(这次暂时忽略 Guest OS)。
先看测试过程中,虚拟机的 CPU 消耗情况。
top -H -p 36256

win_fio1
从上图来看,QEMU 主线程的 cpu 负载已经达到 90%以上,似乎符合 on cpu 类问题。通常来说,解决这类问题最好的办法就是用 perf 进程采样,然后生成火焰图,因为首先查看 CPU 具体消耗在什么地方是一个不错的选择。
perf record -a -g -p 36256 sleep 20
生成火焰图:

win2008-bad
可以清楚的看到,cpu 大部分消耗都是 KVM 的操作,其中最主要的消耗是 vmx_handle_exit。(真实的火焰图是一个矢量图,用浏览器查看很容易确认)。这里引起 vmx_handle_exit 主要有两点:
•访问 IO Port(handle_pio)
•访问 MMIO(handle_apic_access)
既然 KVM 模块占了大部分,那就更希望了解测试时 KVM 的真实行为,通过另一个工具 (kvm_stat) 可以达到。

kvm_pio
除 VM Entry 和 VM Exit 事件外,最高的就是 kvm_pio 和 kvm_mmio,说明 Windows 确实有大量 IO Port 和 MMIO 操作,这也验证了在火焰图上所得出的结论。
在虚拟化里,IO Port 或者 MMIO 都可能引起 VM Exit,甚至是 Heavy Exit。如果需要改善性能,一般都会尽量避免这种情况,至少避免 Heavy Exit.

•具体访问哪些 IO Port 和 MMIO 导致的 VM Exit?

对于这个问题,KVM 模块已经加了很多 trace event,上面的 kvm_stat 也是利用这些 trace event,只是并没有把具体 trace event 信息打印出来。为了获取 trace-event 的信息,有很多前端工具,如 trace-cmd、perf,都是不错的选择。
• 查看所有 kvm 模块的 trace event
[xs3c@devhost1]# trace-cmd list -e | grep kvm
kvmmmu:kvm_mmu_pagetable_walk
kvmmmu:kvm_mmu_paging_element
kvmmmu:kvm_mmu_set_accessed_bit
kvmmmu:kvm_mmu_set_dirty_bit
kvmmmu:kvm_mmu_walker_error
kvmmmu:kvm_mmu_get_page
kvmmmu:kvm_mmu_sync_page
kvmmmu:kvm_mmu_unsync_page
kvmmmu:kvm_mmu_zap_page
kvm:kvm_entry
kvm:kvm_hypercall
kvm:kvm_pio
kvm:kvm_cpuid
kvm:kvm_apic
kvm:kvm_exit
kvm:kvm_inj_virq
kvm:kvm_inj_exception
kvm:kvm_page_fault
kvm:kvm_msr
kvm:kvm_cr
kvm:kvm_pic_set_irq
kvm:kvm_apic_ipi
kvm:kvm_apic_accept_irq
kvm:kvm_eoi
kvm:kvm_pv_eoi
kvm:kvm_write_tsc_offset
kvm:kvm_ple_window
kvm:kvm_vcpu_wakeup
kvm:kvm_set_irq
kvm:kvm_ioapic_set_irq
kvm:kvm_ioapic_delayed_eoi_inj
kvm:kvm_msi_set_irq
kvm:kvm_ack_irq
kvm:kvm_mmio
KVM 模块添加了许多 trace event 的点,这里只抓起其中两个——kvm:kvm_pio 和 kvm:kvm_mmio。

trace-cmd-pio-mmio

通过统计发现主要访问的:
•IO Port 是 0x608 和 0xc050;
•MMIO 是 0xFEE003xx
经由 qemu info mtree 命令,可以查看 IO Port 608、c050 以及 FEE003xx 分别对应的具体设备。
•IO Port
0000000000000608-000000000000060b (prio 0, RW): acpi-tmr 000000000000c040-000000000000c07f (prio 1, RW): virtio-pci
•MMIO
00000000fee00000-00000000feefffff (prio 4096, RW): icc-apic-container
c050 可以忽略,这个被 Virtio Block 来做 VM Exit。
到目前为止,可以判断出 wnidows 大量读取 ACPI Power Manager Timer 以及访问 APIC 寄存器,进而导致过多 vm exit 产生,消耗大量 CPU 资源,因此就可以具体讨论两个问题:
1. 如何减少读取 ACPI PM Timer 寄存器而引起的 VM Exit;
2. 如何减少访问 APIC MMIO 导致的 VM Exit。

如何减少读取 ACPI PM Timer 而引起的 VM Exit?
从虚拟化层优化的思路来说,减少 IO Port 引发的 VM Exit 通常会考虑是否可以利用 Paravirtulization 替换 Full-virtualization 以达到目的,来看 Windows 在这方面是如何做的。
从 Windows 7 开始,微软为了使 Windows 操作系统能够在 HyperV 得到更好性能,特意为 Windows 系统做了很多虚拟化方面的增强工作,其中就包括这里可以利用到的 HyperV Timer,这个特性类似于 Linux 中的 kvmclock。
从当前的支持情况来看:
•Windows 7
•Windows 7 SP1
•Windows Server 2008 R2
•Windows Server 2008 R2 SP1/SP2
•Windows 8/8.1/10
•Windows Server 2012
•Windows Server 2012 R2
这些 Windows 系统都包含虚拟化增强功能,更多的信息在微软官方网站。
2014 年,RedHat 工程师 Vadim Rozenfeld 和 Peter Krempa 分别为 qemu 和 libvirt 添加了 HyperV Timer 的支持,所以可以直接通过 libvirt 使能 HyperV Timer。

clock …

timer name=’hypervclock’present=’yes’/

/clock

另外,KVM 里很早也支持了 HyperV Timer,只是客户的宿主机内核版本并不支持该功能,所以需要为客户升级 UCloud 自己维护的内核版本。
•如何减少 APIC ACCESS 而引起 VM Exit?
Intel CPU 也已经支持 apic-v,同样升级到 UCloud 自己维护的内核版本来解决。
最终效果

win-fio-good

win-good

从这个案例可以看出,跟物理环境相比,在虚拟化环境下,Windows IO 性能较差时,并不一定真正是 IO 路径出现问题,可能是一些虚拟化性能的问题对 IO 性能造成了很大影响。

以上就是虚拟化环境下 Windows IO 性能的解析是怎样的,丸趣 TV 小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注丸趣 TV 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4412字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)