KVM性能优化--CPU篇

http://bbs.qy.com.cn/thread-1111-1-1.html

一、 NUMA
1. NUMA 介绍
    早期的时候,每台服务器都是单CPU,随着技术的发展,出现了多CPU共同工作的需求。
    NUMA(Non-Uniform Memory Access,非一致性内存访问)和SMP(Symmetric Multi-Processor,对称多处理器系统)是两种不同的解决多CPU共同工作的硬件体系架构。
    SMP的主要特征是共享,所有的CPU共享使用全部资源,例如内存、总线和I/O,多个CPU对称工作,彼此之间没有主次之分,平等地访问共享的资源,这样势必引入资源的竞争问题,从而导致它的扩展内力非常有限。
   
    NUMA技术将CPU划分成不同的组(Node),每个Node由一个或多个(物理)CPU组成,并且有独立的本地内存、I/O等资源。Node之间通过互联模块连接和沟通,因此除了本地内存外,每个CPU仍可以访问远端Node的内存,只不过效率会比访问本地内存差一些。(我们用Node之间的距离Distance来定义各个Node之间互访资源的开销。)所以,NUMA调优的目的是让处理器尽量访问自己的存储器,以提高处理速度。


NUMA支持的软硬件要求:
硬件方面,英特尔从Xeon(至强)5500 处理器开始采用NUMA架构。
软件方面,Windows Server 2003 和Windows XP 64-bit Edition, Windows XP等都是NUMA aware的,而Windows Vista/7/2008 Server则有了对Numa调度的支持。所有使用2.6版本以上kernel的Linux操作系统都能够支持NUMA。而Solaris,HP-Unix等UNIX操作系统也是充分支持NUMA架构的。对于数据库来说,SQL Server 2005 开始支持NUMA的支持。

Linux下,使用命令numactl --hardware 查看当前物理CPU的numa情况:

  1. [root@qycn46 ~]# numactl --hardware
  2. available: 2 nodes (0-1)                 # 本服务器有两个node,分别为node0 和 node1
  3. node 0 cpus: 0 1 2 3                       # node 0 包含的CPU
  4. node 0 size: 16375 MB                   # node 0 的内存16G
  5. node 0 free: 2616 MB                    
  6. node 1 cpus: 4 5 6 7                       # node 1 包含的CPU
  7. node 1 size: 16384 MB                   # node 1 的内存16G
  8. node 1 free: 2118 MB
  9. node distances:
  10. node   0   1
  11.   0:  10  21                                            # node内访问内存的distance是10,跨node访问的distance为21
  12.   1:  21  10                                            # 远端访问的开销是本地访问的2.1倍
  13. [root@qycn46 ~]#
复制代码

2. CPU Topology
    在NUMA架构下,CPU的概念从大到小依次是:Node、Socket、Core、Processor。
    随着多核技术的发展,我们将多个CPU封装在一起,这个封装一般被称为Socket(插槽),而Socket中的每个核心被称为Core。为了进一步提升CPU的处理能力,Intel又引入了HT(Hyper-Threading,超线程)的技术,一个Core打开HT之后,在OS看来就是两个核,当然这个核是逻辑上的概念,所以也被称为Logical Processor,本文简称为Processor。
    综上所述,一个NUMA Node可以有一个或者多个Socket,一个多核Socket显然包含多个Core,一个Core如果打开HT则变成两个Logical Processor。
    Linux中,CPU的Socket, Core, Processor 信息都可以通过 /proc/cpuinfo 文档查询,这里列出实验物理机的cpu特性如下:

3. NUMA调度优化
查看虚拟机的NUMA配置
  1. [root@qycn46 ~]# virsh list --all
  2. Id Name State
  3. ----------------------------------------------------
  4. 3 VM3 running
  5. 16 test running
  6. - VM1 shut off

  7. [root@qycn46 ~]# virsh numatune test
  8. numa_mode : strict
  9. numa_nodeset : 0-1

  10. [root@qycn46 ~]#
复制代码
输出结果显示,该虚拟机test VCPU限定在node0-1内。(但前面已经看到,宿主机本就只有两个node,所以这里相当于没有限制。)虚拟机配置文件相应部分如下:

这里需要注意,如果 设置了placement='auto',则的placement 也应为auto,如下图所示。

可以使用以下命令来设置将虚拟机绑定到指定node。
  1. virsh numatune domain --nodeset 'string'
复制代码

举个列子:将上面的虚拟机test(6核),限定在Node0和1中,使用物理机六个CPU1,2,3,4,6,7。
(注:本例中由于一个socket仅有4个CPU,不能满足虚拟机 test的需求,所以例子对NUMA性能并没有改善,但这里的重点是示范操作过程。)
a. 先观察未做NUMA设置之前,虚拟机test对物理机CPU的使用情况:

b. virsh numatune test --nodeset '0-1'
c. 打开虚拟机配置文件,在 部分添加 cpuset='1-7,^5'

d. 重启虚拟机(不知道怎样不重启就立即生效,后续再研究。。。),再次查看虚拟机CPU情况:

可以发现,设置后,虚拟机vcpu仅运行在物理机CPU1-4和6-7中。
假如本例中的服务器CPU支持超线程,则一个socket就有8个CPU,这样,我们就可以将虚拟机test的6核限定在一个socket(一个Node)内,使用最小的distance10开销,这样就提高了效率。)
什么是 CPU Affinity (处理器亲和性)?
    进程的处理器亲和性,即是CPU的绑定设置,是指将进程绑定到特定的一个或多个CPU上去执行,而不允许调度到其他的CPU上。
    设置进程的处理器亲和性带来的好处是可以减少进程在多个CPU之间交换运行带来的缓存命中失效(cache missing),从该进程运行的角度来看,可能带来一定程度上的性能提升。换个角度来看,对进程亲和性的设置也可能带来一定的问题,如破坏了系统对各CPU的负载均衡,这有可能会导致整个系统的进程调度变得低效。
    对虚拟机 中的cpuset做配置,会体现在CPU Affinity中。


二、 虚拟机VCPU的绑定
CPU绑定规则:
    从大的范围来看,虚拟机所有的VCPU应尽可能在同一个Node内,减少内存访问开销。细化下来,对于物理 CPU,同一个 core 的 threads 共享 L2 Cache,同一个 socket 的 cores 共享 L3 cache,所以虚拟机的 VCPU 也应当尽可能在同一个 core 和 同一个 socket 中,增加 cache 的命中率,从而提高性能。所以,具体的绑定策略,应该根据宿主机物理CPU特性和虚拟机VCPU个数来定。
(1) VCPU个数不大于2个,且物理机CPU支持超线程,则可以将VCPU绑定到同一个core内。
(2) VCPU个数不大于物理机一个Socket的总逻辑Processor个数,则可以将VCPU绑定到同一个Socket中。
(3) VCPU个数不大于物理机一个Node的总逻辑Processor个数,则可以将VCPU绑定到同一个Node中。
(4) 根据实际情况,物理机某Processor使用率很高导致虚拟机很卡,则可及时将虚拟机绑定到物理机其他较空闲的Processor。

CPU在线绑定方法:
1. 区域绑定
(注意:继续下面的实验前,请先取消上面的NUMA设置及对中cpuset的设置,否则下面的设置将不生效。)
Emulator标签可以为虚拟机指定物理机的任意逻辑Processor, 下面的指令可以 在线调整CPU绑定情况。
  1. virsh emulatorpin domain 'string'
复制代码
a. 设置前,先观察当前虚拟机对物理机CPU的使用情况:

b. 修改emulator的设置 virsh emulatorpin test '1-4,6-7',再查看虚拟机VCPU状态

由上图发现,emulator的设置似乎没有生效,因为VCPU3竟然运行在物理机CPU5上,而CPU5在上面的设置中是排除了的。
还需继续实验验证是哪里的问题。   ?????
c. 查看emulatorpin的在xml文件中的表现形式:

(内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh emulatorpin变更CPU绑定后,都需要将内存中的设置copy到xml中并保存。)

2. 一对一绑定
可以使用 virsh vcpupin 指令强制VCPU与物理逻辑Processor一对一绑定,具体指令如下:
  1. virsh vcpupin domain vcpu# Processor#
复制代码
比如,上面我们已经将虚拟机VCPU限定在物理Processor1,2,3,4,6和7中,现在更进一步,将VCPU与前面的物理Processor按顺序一一绑定:
  1. virsh vcpupin test 0 1
  2. virsh vcpupin test 1 2
  3. virsh vcpupin test 2 3
  4. virsh vcpupin test 3 4
  5. virsh vcpupin test 4 6
  6. virsh vcpupin test 5 7
复制代码
然后通过virsh vcpuinfo test 来查看一下虚拟机VCPU情况:

查看一下vcpupin设置在xml文件中的表现形式:

(同样的,内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh vcpupin变更CPU绑定后,都需要将内存中的设置copy到xml中并保存。)


三、 虚拟机多VCPU的设定方法
可参考 KVM虚拟机操作常见问题 的第一条


四、在线添加CPU
(1) 在创建CPU的时候,设置maxvcpu参数,且当前vcpu数量小于maxvcpu数量,即可使用
  1. virsh setvcpus domain cpunum# --live
复制代码

如图,虚拟机tst当前CPU个数为3,设置后,CPU数目动态变为4个。

查看该配置在xml 中的表现形式:

(同样的,内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh setvcpus变更CPU数量后,都需要将内存中的设置中的current 数量修改到xml中并保存。)

(2) 也可以直接按上图所示格式修改虚拟机的配置文件xml。
a. 在 内添加currrent 参数,后接虚拟机当前VCPU数量(也可以为希望调整的VCPU数量),两个尖括号中间的值为最大VCPU数量(需不小于current数量)。
b. 重启虚拟机,此时最大VCPU的设置生效。
c. 后续若需要再次调整CPU数目,使用virsh setvcpus tst # --live 即可。

注意:centos6.7 系统的宿主机和虚拟机上,可在最大VCPU范围内随意更改VCPU个数,但是在centos7.1 系统的宿主机和虚拟机上,VCPU个数只能增加,不能减少。
综上所述,如果想在线添加VCPU数量,还是要未雨绸缪,在创建虚拟机时就先设置好 maxvcpu 参数,这样后面修改时才不必重启虚拟机。

你可能感兴趣的:(qemu-kvm,虚拟化)