原文:https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/virtualization_tuning_and_optimization_guide/
KVM总结-KVM性能优化之磁盘IO优化-----------https://blog.csdn.net/dylloveyou/article/details/71515880
KVM CPU(http://blog.csdn.net/dylloveyou/article/details/71169463)、
KVM 内存(http://blog.csdn.net/dylloveyou/article/details/71338378)
第 1 章 简介
1.1. KVM 概述
 
    图 1.1. KVM 构架
1.2. KVM 性能构架概述
-  
     使用 KVM 时,客机作为一个 Linux 的进程在主机上运行。
 -  
     虚拟 CPU(vCPU)作为正常线程执行,由 Linux 调度器执行。
 -  
     客机会继承诸如内核中的 NUMA 和大页面一类的功能。
 -  
     主机中的磁盘和网络 I/O 设置对性能有显著影响。
 -  
     网络流量通常通过基于软件的网桥传送。
 
1.3. 虚拟化性能特性和改进
Red Hat Enterprise Linux 7 中虚拟化性能的改进
- 自动化 NUMA 平衡
 -  
     自动化 NUMA 平衡改进了 NUMA 硬件系统中运行应用的性能,且无需为 Red Hat Enterprise Linux 7 客机进行任何手动调试。自动化 NUMA 平衡把任务(任务可能是线程或进程)移到与它们需要访问的内存更近的地方。如需获取关于自动化 NUMA 平衡的更多信息,请参照 第 8.3 节 “自动化 NUMA 平衡”。
 - 多队列 virtio-net
 -  
     联网方法使数据包发送/接收处理与客机中可用的虚拟 CPU 数量相协调。关于多队列 virtio-net 的更多信息请参照 第 5.5.2 节 “多队列 virtio-net”。
 - 桥接零复制传输
 -  
     在客机网络和外部网络间传输大数据包中,零复制传输模式(Zero Copy Transmit)对主机 CPU 负荷的减少可以达到 15%,且对吞吐量没有影响。Red Hat Enterprise Linux 7 虚拟机中全面支持桥接零复制传输(Bridge Zero Copy Transmit),但在默认情况下被禁用。关于零复制传输的更多信息请参照 第 5.5.1 节 “桥接零复制传输”。
 - APIC 虚拟化
 -  
     更新的 Intel 处理器提供高级可编程中断控制器的硬件虚拟化(APICv,Advanced Programmable Interrupt Controller)。APIC 虚拟化将通过允许客机直接访问 APIC 改善虚拟化 x86_64 客机性能,大幅减少中断等待时间和高级可编程中断控制器造成的虚拟机退出数量。更新的 Intel 处理器中默认使用此功能,并可改善 I/O 性能。
 - EOI 加速
 -  
     对在那些较旧的、没有虚拟 APIC 功能的芯片组上的高带宽 I/O 进行 EOI 加速处理。
 - 多队列 virtio-scsi
 -  
     改进的存储性能和 virtio-scsi 驱动中多队列支持提供的可扩展性。这个命令使每个虚拟 CPU 都可以使用独立的队列和中断,从而不会影响到其他虚拟 CPU。关于多队列 virtio-scsi 的更多信息请参照 第 6.5.2 节 “多队列 virtio-scsi”。
 - 半虚拟化 ticketlocks
 -  
     半虚拟化 ticketlocks(pvticketlocks)将改善包括过度订阅 CPU 在内的 Red Hat Enterprise Linux 主机中运行的 Red Hat Enterprise Linux 7 客户虚拟机的性能。
 - 半虚拟化页面错误
 -  
     半虚拟化页面错误在尝试访问主机置换页面时将被加入到客机。这一功能改善了主机内存过载和客机内存被置换时 KVM 的客机性能。
 -  
     半虚拟化时间 
vsyscall优化 -  
     
gettimeofday和clock_gettime系统调用将通过vsyscall机制在用户空间执行。在此之前,调用这类系统触发需要系统切换到 kernel 模式,之后退回到用户空间。这一操作将极大改善部分应用的性能。 
Red Hat Enterprise Linux 中的虚拟化性能特性
-  
     CPU/Kernel
-  
        NUMA——非一致性内存访问。关于 NUMA 的详细信息请参照 第 8 章 NUMA。
 -  
        CFS——完全公平调度程序。一种新的、使用类(class)的调度程序。
 -  
        RCU——读取复制更新。更好地处理共享线程数据。
 -  
        多达 160 种虚拟 CPU(vCPU)。
 
 -  
        
 -  
     内存
-  
        大页面和其他内存密集型环境下的优化。详细信息请参照 第 7 章 内存。
 
 -  
        
 -  
     联网
-  
        vhost-net——一种基于内核的 VirtIO 快速解决方案。
 -  
        SR-IOV——使联网性能级别接近本机。
 
 -  
        
 -  
     块 I/O
-  
        AIO——支持线程和其他 I/O 操作重叠。
 -  
        MSI - PCI 总线设备中断生成。
 -  
        磁盘 I/O 节流——客机磁盘 I/O 的控制要求避免过度使用主机资源。详细信息请参照 第 6.5.1 节 “磁盘 I/O 节流”。
 
 -  
        
 
注意
第 2 章 性能监控工具
2.1. 简介
2.2. perf kvm
kvm 选项的  
   perf 命令,从主机收集客机运行系统的统计数据。 
  perf 命令。运行 rpm -q perf 检查 perf软件包是否已安装。如果没有安装且您想安装该软件包来收集分析客机运行系统统计数据,请以 root 用户运行以下命令: 
   # yum install perf
perf kvm,您需要从客户端获取  
   /proc/modules 和  
   /proc/kallsyms 文件。有两种可实现的方法。参考以下程序,用 
   过程 2.1, “从客户端向主机复制 proc 文件” 将文件转换逐级并在文件中运行报告。或者参照 
   过程 2.2, “备选:使用 sshfs 直接访问文件” 直接安装客户端来获取文件。 
  过程 2.1. 从客户端向主机复制 proc 文件
重要
scp 命令),您只会复制零长度的文件。此处描述了首先将客户端中的文件复制到临时位置(通过 
      cat 命令),然后通过  
      perf kvm 命令将它们复制到主机使用的过程。 
     -  
登录客户端并保存文件
登录客户端并将/proc/modules和/proc/kallsyms保存到临时位置,文件名为/tmp:# cat /proc/modules > /tmp/modules # cat /proc/kallsyms > /tmp/kallsyms
 -  
将临时文件复制到主机
在您退出客户端之后,运行以下scp命令,将已保存的文件复制到主机。如果 TCP 端口和主机名称不符,应替换主机名称:# scp root@GuestMachine:/tmp/kallsyms guest-kallsyms # scp root@GuestMachine:/tmp/modules guest-modules
现在您在主机上拥有了两个客户端的文件(guest-kallsyms和guest-modules),准备就绪通过perf kvm命令进行使用。 -  
通过 perf kvm 对事件进行记录和报告
使用前一步骤中获取的文件,并纪录和报告客户端或(与)主机中的事件现在是可行的。运行以下示例命令:# perf kvm --host --guest --guestkallsyms=guest-kallsyms \ --guestmodules=guest-modules record -a -o perf.data
注意
如果 --host 和 --guest 均在命令中使用,输出将被储存在perf.data.kvm中。如果只有 --host 被使用,文件将被命名为perf.data.host。同样地,如果仅有 --guest 被使用,文件将被命名为perf.data.guest。请按 Ctrl-C 停止纪录。 -  
报告事件
以下示例命令使用纪录过程中获取的文件,并将输出重新定向到一个新文件:analyze。perf kvm --host --guest --guestmodules=guest-modules report -i perf.data.kvm \ --force > analyze
查看并分析analyze文件内容,检测纪录的事件:# cat analyze # Events: 7K cycles # # Overhead Command Shared Object Symbol # ........ ............ ................. ......................... # 95.06% vi vi [.] 0x48287 0.61% init [kernel.kallsyms] [k] intel_idle 0.36% vi libc-2.12.so [.] _wordcopy_fwd_aligned 0.32% vi libc-2.12.so [.] __strlen_sse42 0.14% swapper [kernel.kallsyms] [k] intel_idle 0.13% init [kernel.kallsyms] [k] uhci_irq 0.11% perf [kernel.kallsyms] [k] generic_exec_single 0.11% init [kernel.kallsyms] [k] tg_shares_up 0.10% qemu-kvm [kernel.kallsyms] [k] tg_shares_up [输出删节……] 
过程 2.2. 备选:使用 sshfs 直接访问文件
-  
     
重要
这一步仅被作为一个提供的示例。您需要依据环境替换属性值。# Get the PID of the qemu process for the guest: PID=`ps -eo pid,cmd | grep "qemu.*-name GuestMachine" \ | grep -v grep | awk '{print $1}'` # Create mount point and mount guest mkdir -p /tmp/guestmount/$PID sshfs -o allow_other,direct_io GuestMachine:/ /tmp/guestmount/$PID # Begin recording perf kvm --host --guest --guestmount=/tmp/guestmount \ record -a -o perf.data # Ctrl-C interrupts recording. Run report: perf kvm --host --guest --guestmount=/tmp/guestmount report \ -i perf.data # Unmount sshfs to the guest once finished: fusermount -u /tmp/guestmount 
2.3. 虚拟性能监控单位
arch_perfmon 标识: 
  # cat /proc/cpuinfo|grep arch_perfmon 
  host-passthrough 在客户虚拟机中指定  
   cpu mode: 
  # virsh dumpxml guest_name |grep "cpu mode"
<cpu mode='host-passthrough'> 
  perf 命令显示虚拟机的性能数据。 
  第 3 章 virt-manager
3.1. 简介
3.2. 操作系统细节和设备
3.2.1. 客户虚拟机细节详述
 
      图 3.1. 提供操作系统类型和版本
3.2.2. 删除不使用的设备
 
      图 3.2. 移除不使用的设备
3.3. CPU 性能选项
 
    图 3.3. CPU 性能选项
3.3.1. 选项:可用的 CPU
 
      图 3.4. 过度使用 CPU
重要
3.3.2. 选项:CPU 配置
 
      图 3.5. CPU 配置选项
注意
注意
virsh capabilities 命令,查看系统虚拟化功能,包括 CPU 类型和 NUMA 功能。 
     3.3.3. 选项:CPU 拓扑
 
      图 3.6. CPU 拓扑选项
注意
3.3.4. 选项:CPU 钉选(pinning)
 
      图 3.7. CPU 钉选
警告
lscpu 命令输出,使用  
    virsh cpupin 在虚拟 CPU 绑定建立 1:1 物理 CPU。NUMA 和 CPU 钉选的更多信息请参照 
    第 8 章 NUMA。 
   3.4. 虚拟磁盘性能选项
 
     图 3.8. 虚拟磁盘性能选项
重要
第 4 章 tuned
4.1. 简介
4.2. tuned 和 tuned-adm
-  
     
virtual-guest -  
     基于
throughput-performance文件,virtual-guest同样会降低虚拟内存的 swappiness。在创建 Red Hat Enterprise Linux 7 客户虚拟机时,virtual-guest文件将被自动选择。建议虚拟机使用该文件。本文件在 Red Hat Enterprise Linux 6.3 和之后可用,但在安装虚拟机时须手动选择。 -  
     
virtual-host -  
     基于
throughput-performance文件,virtual-host也会降低虚拟内存的 swappiness,并启用更积极的脏页(dirty page)回写。建议虚拟化主机使用本文件,包括 KVM 和 Red Hat Enterprise Virtualization 主机。 
tuned 服务。 
  # tuned-adm list
Available profiles:
- balanced
- desktop
- latency-performance
- network-latency
- network-throughput
- powersave
- sap
- throughput-performance
- virtual-guest
- virtual-host
Current active profile: throughput-performance 
  tuned.conf 手册页。 
  tuned-adm active 
  tuned-adm profile profile_name 
  virtual-host 文件,请运行: 
  tuned-adm profile virtual-host 
  重要
tuned-adm off 
  注意
第 5 章 联网
5.1. 简介
5.2. 联网调试须知
-  
     使用多个网络以避免单一网络过载。例如用专用网络进行管理、备份及/或实时迁移。
 -  
     通常,在所有组件中可以满足匹配最大传输单元(1,500字节)。如果需要更大的消息,提高最大传输单元值可以减少碎片。如果改变了最大传输单元,路径中所有的设备都应该有一个匹配的最大传输单元值。
 -  
     使用
arp_filter阻止 ARP Flux,这种不良情况可能会在主机和客机中发生,造成这一现象的原因是机器从一个以上网络界面响应 ARP请求:运行echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter或编辑/etc/sysctl.conf让重启后这设置得以持续。 
注意
5.3. Virtio 和 vhost_net
 
    图 5.1. Virtio 和 vhost_net 构架
5.4. 设备分配和 SR-IOV
 
    图 5.2. 设备分配和 SR-IOV
5.5. 网络调试技巧
5.5.1. 桥接零复制传输
experimental_zcopytx kernel 模块参数设置到 1。 
   注意
experimental_zcopytx 设置到 0 被禁用。 
   5.5.2. 多队列 virtio-net
-  
      流量数据包相对较大。
 -  
      客机同时在各种连接中活跃,流量从客机、客机到主机或客户端运行到外部系统。
 -  
      队列数量与虚拟 CPU 相同。因为多队列支持可以优化 RX 中断关联和 TX 队列选择,实现特定队列对于特定虚拟 CPU 的私有化。
 
注意
5.5.2.1. 配置多队列 virtio-net
<interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
      <driver name='vhost' queues='N'/>
</interface> 
    # ethtool -L eth0 combined M 
   第 6 章 块 I/O
6.1. 简介
6.2. 块 I/O 调试
virsh blkiotune 命令允许管理员在客机 XML 配置的  
   <blkio> 元素中,手动设置或显示客户虚拟机的块 I/O 参数。 
  <blkio> 参数: 
  # virsh blkiotune virtual_machine
<blkio> 参数,请参照以下命令并依据环境替换属性值: 
  # virsh blkiotune virtual_machine [--weight number] [--device-weights string] [--config] [--live] [--current] 
  -  
     
weight -  
     I/O 的权重范围在 100 到 1,000 之间。
 -  
     
device-weights -  
     列出一个或多个设备/权值组群的单独字符串,以
为格式。每一个权值必须在 100-1,000 范围内,或者 0 值从每一个设备列表删除该设备。只修改字符串中列出的设备;任何现有的其它设备的权值保持不改变。/path/to/device,weight,/path/to/device,weight -  
     
config -  
     添加
选项,使更改在下次启动时生效。--config -  
     
live -  
     添加
选项,在运行的虚拟机中应用这些更改。--live注意
选项要求监控程序支持这一行为。并非所有监控程序都允许最大内存限制的实时更改。--live -  
     
current -  
     添加
选项,在当前的虚拟机中应用这些更改。--current 
注意
virsh blkiotune 命令使用的更多信息,请参照  
     # virsh help blkiotune。 
    6.3. 缓存
表 6.1. 缓存选项
| 缓存选项 | 描述 | 
|---|---|
| Cache=none | 客机中的 I/O 不能在主机上缓存,但可以保留在回写磁盘缓存中。在客机中使用此选项来应对较大的需求。此选项通常是支持迁移的最佳和唯一选项。 | 
| Cache=writethrough | 客机中的 I/O 在主机上缓存,但在物理媒介中直写。该模式较慢且更易造成缩放问题。最好是在客机数量较小且 I/O 需求较低的情况下使用。推荐的应用对象是无需迁移、不支持回写缓存的客机(如 Red Hat Enterprise Linux 5.5 或更早的版本)。 | 
| Cache=writeback | 客机中的 I/O 在主机上缓存。 | 
| Cache=directsync | 与 writethrough 相似,但客机中的 I/O 将忽略主机页面缓存。 |  
      
| Cache=unsafe | 主机可能会缓存所有的 I/O 磁盘,客机的同步要求将被忽略。 | 
| Cache=default | 如果没有指定缓存模式,将会选择系统默认设置。 | 
driver 标签内部的  
   cache,指定一个缓存选项。例如,将缓存设置为  
   writeback: 
   <disk type='file' device='disk'>  
          <driver name='qemu' type='raw' cache='writeback'/> 
  6.4. I/O 模式
表 6.2. IO 模式选项
| IO 模式选项 | 描述 | 
|---|---|
| IO=native | Red Hat Enterprise Virtualization 环境的默认值。该模式适用于直接 I/O 选项的 kernel 非同步 I/O。 | 
| IO=threads | 默认为基于主机用户模式的线程。 | 
| IO=default | Red Hat Enterprise Linux 7 默认为线程模式。 | 
driver 标签中的  
   io 设置,指定  
   native、 
   threads 或  
   default。例如,将 I/O 模式设置为  
   threads: 
   <disk type='file' device='disk'>  
          <driver name='qemu' type='raw' io='threads'/> 
  6.5. 块 I/O 调试技术
6.5.1. 磁盘 I/O 节流
virsh blkdeviotune 命令为虚拟机设置 I/O 限制。请参照以下示例: 
   # virsh blkdeviotune virtual_machine device --parameter limit
<target dev='name'/>)或来源文件( 
    <source file='name'/>)。使用  
    virsh domblklist 命令获取磁盘设备名称列表。 
   -  
      
total-bytes-sec -  
      字节每秒的总吞吐量限制。
 -  
      
read-bytes-sec -  
      字节每秒的读取吞吐量限制。
 -  
      
write-bytes-sec -  
      字节每秒的写入吞吐量限制。
 -  
      
total-iops-sec -  
      每秒的 I/O 操作总量限制。
 -  
      
read-iops-sec -  
      每秒的读取 I/O 操作限制。
 -  
      
write-iops-sec -  
      每秒的写入 I/O 操作限制。
 
virtual_machine 虚拟机中的  
    vda 节流至 I/O 每秒 1000、吞吐量为每秒 50 MB,请运行以下命令: 
   # virsh blkdeviotune virtual_machine vda --total-iops-sec 1000 --total-bytes-sec 52428800
6.5.2. 多队列 virtio-scsi
6.5.2.1. 配置多队列 virtio-scsi
   <controller type='scsi' index='0' model='virtio-scsi'>
   <driver queues='N' />
    </controller> 
   第 7 章 内存
7.1. 简介
7.2. 内存调试须知
-  
     请勿为客机分配超过所需的其它资源。
 -  
     在可能的情况下,如果 NUMA 节点中有足够的资源,将一台客机分配到一个单一 NUMA 节点。关于 NUMA 使用的更多信息,请参照 第 8 章 NUMA。
 
7.3. 虚拟机内存调试
7.3.1. 内存监控工具
-  
       
top -  
       
vmstat -  
       
numastat -  
       
/proc/ 
注意
7.3.2. 使用 virsh 调试内存
<memtune> 元素允许管理员手动配置客户虚拟机内存设置。如果省略  
    <memtune>,内存设置将被默认应用。 
   virsh memtune 命令显示或设置虚拟机  
    <memtune> 元素中的内存参数,依据环境替换属性值: 
   # virsh memtune virtual_machine --parameter size
-  
      
hard_limit -  
      虚拟机可以使用的最大内存,单位是千字节(1,024 字节块)
警告
该限制设置过低可导致虚拟机被内核终止。 -  
      
soft_limit -  
      发生内存争用时,内存限制使用的单位是千字节(1,024字节块)。
 -  
      
swap_hard_limit -  
      虚拟机加上转化可使用的最大内存,单位是千字节(1,024 字节块)。
swap_hard_limit参数值必须大于hard_limit参数值。 -  
      
min_guarantee -  
      保证分配给虚拟机可以使用的最小内存,单位是千字节(1,024 字节块)。
 
注意
virsh memtune 命令的更多信息请参照  
      # virsh help memtune。 
     <memoryBacking> 元素可能包含若干影响主页存储备份虚拟内存页面的元素。 
   locked 会阻止主机交换属于客机的内存页面。向客机 XML 添加以下命令,锁定主机内存中的虚拟内存页面: 
   <memoryBacking>
        <locked/>
</memoryBacking> 
   重要
locked 时,必须在  
      <memtune> 元素中设置  
      hard_limit,使其达到客机配置的最大内存,以及该进程本身所消耗的内存。 
     nosharepages 阻止主机合并在客机间使用的相同内存。通过向客机的 XML 添加以下命令,指示虚拟机监控程序禁用与客机的共享页面: 
   <memoryBacking>
         <nosharepages/>
</memoryBacking> 
  7.3.3. 大页面和透明大页面(THP)
过程 7.1. 为客机启用 1GB 大页面
-  
      Red Hat Enterprise Linux 7.1 系统支持 2MB 或 1GB 大页面,分配将在启动或运行时进行。页面大小均可以在运行时被释放。例如,在启动时分配 4 个 1GB 的大页面和 1,024 个 2MB 的大页面,请使用以下命令行:
'default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=1024'
此外,大页面还可以在运行时分配。运行时分配允许系统管理员选择从何种 NUMA 模式分配页面。然而由于内存碎片的存在,运行时的页面分配会比启动时分配更容易造成分配失败。以下运行时的分配示例显示了从node1分配 4 个 1GB 的大页面以及从node3分配 1,024 个 2MB 的大页面:# echo 4 > /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/nr_hugepages # echo 1024 > /sys/devices/system/node/node3/hugepages/hugepages-2048kB/nr_hugepages
 -  
      接下来,将 2MB 和 1GB 的大页面挂载到主机:
# mkdir /dev/hugepages1G # mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G # mkdir /dev/hugepages2M # mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M
 -  
      重启 libvirtd,使 1GB 大页面可以在客机上启用:
# systemctl restart libvirtd
 
7.3.3.1. 透明大页面配置
/sys/kernel/mm/transparent_hugepage/enabled 被设置为  
     always,透明大页面将被默认使用。运行以下命令禁用透明大页面: 
    # echo never > /sys/kernel/mm/transparent_hugepage/enabled 
    7.3.3.2. 静态大页面配置
virsh edit 向客机 XML 配置添加以下命令: 
    <memoryBacking>
        <hugepages/>
</memoryBacking> 
    <memoryBacking> 元素中指定大页面的大小、单位和客机的 NUMA 节点集。关于配置的更多信息和具体示例,请参照 
     第 8.4.9 节 “向多个客机 NUMA 节点指定主机大页面”。 
    cat /proc/sys/vm/nr_hugepages 
    过程 7.2. 大页面设置
-  
       查看当前的大页面值:
# cat /proc/meminfo | grep HugeAnonHugePages: 2048 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB -  
       大页面将以 2MB 为增量进行设置。将大页面的数量设置到 25,000,请运行以下命令:
echo 25000 > /proc/sys/vm/nr_hugepages注意
此外,如需进行永久设置,请使用# sysctl -w vm.nr_hugepages=N命令和显示为大页面数量的 N。 -  
       大页面挂载:
# mount -t hugetlbfs hugetlbfs /dev/hugepages -  
       重启 libvirtd,之后再运行以下命令重启虚拟机:
# systemctl start libvirtd# virsh start virtual_machine -  
       验证
/proc/meminfo中的更改:# cat /proc/meminfo | grep HugeAnonHugePages: 0 kB HugePages_Total: 25000 HugePages_Free: 23425 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB 
第 8 章 NUMA
8.1. 简介
8.2. NUMA 内存分配策略
-  
     
Strict -  
     目标节点中不能分配内存时,分配将被默认操作转进至其他节点。严格的策略意味着,当目标节点中不能分配内存时,分配将会失效。
 -  
     
Interleave -  
     内存页面将被分配至一项节点掩码指定的节点,但将以轮循机制的方式分布。
 -  
     
Preferred -  
     内存将从单一最优内存节点分配。如果内存并不充足,内存可以从其他节点分配。
 
<numatune>
        <memory mode='preferred' nodeset='0'>
</numatune> 
 8.3. 自动化 NUMA 平衡
-  
     进程内存的周期性 NUMA 取消对应
 -  
     NUMA hinting 故障
 -  
     故障迁移(MoF,Migrate-on-Fault)——将内存移动至需要运行的程序
 -  
     task_numa_placement ——移动运行的程序,使接近其内存
 
8.3.1. 配置自动化 NUMA 平衡
-  
      
# numactl --hardware显示多个节点,以及 -  
      
# cat /sys/kernel/debug/sched_features在标识中显示NUMA 
# echo 0 > /proc/sys/kernel/numa_balancing 
   # echo 1 > /proc/sys/kernel/numa_balancing 
  8.4. libvirt NUMA 调试
numastat 工具对进程和操作系统的每个 NUMA 节点内存统计进行查看。 
  numastat 工具显示了 NUMA 节点中的四种非优化内存排列的虚拟机: 
   # numastat -c qemu-kvm
Per-node process memory usage (in MBs)
PID              Node 0 Node 1 Node 2 Node 3 Node 4 Node 5 Node 6 Node 7 Total
---------------  ------ ------ ------ ------ ------ ------ ------ ------ -----
51722 (qemu-kvm)     68     16    357   6936      2      3    147    598  8128
51747 (qemu-kvm)    245     11      5     18   5172   2532      1     92  8076
53736 (qemu-kvm)     62    432   1661    506   4851    136     22    445  8116
53773 (qemu-kvm)   1393      3      1      2     12      0      0   6702  8114
---------------  ------ ------ ------ ------ ------ ------ ------ ------ -----
Total              1769    463   2024   7462  10037   2672    169   7837 32434 
  numad,使客机 CPU 和内存资源自动对齐。 
  numastat -c qemu-kvm,以查看  
   numad 的运行结果。以下输出显示了资源已对齐: 
   # numastat -c qemu-kvm
Per-node process memory usage (in MBs)
PID              Node 0 Node 1 Node 2 Node 3 Node 4 Node 5 Node 6 Node 7 Total
---------------  ------ ------ ------ ------ ------ ------ ------ ------ -----
51747 (qemu-kvm)      0      0      7      0   8072      0      1      0  8080
53736 (qemu-kvm)      0      0      7      0      0      0   8113      0  8120
53773 (qemu-kvm)      0      0      7      0      0      0      1   8110  8118
59065 (qemu-kvm)      0      0   8050      0      0      0      0      0  8051
---------------  ------ ------ ------ ------ ------ ------ ------ ------ -----
Total                 0      0   8072      0   8072      0   8114   8110 32368 
  注意
numastat 和  
     -c 可提供简洁的输出;添加  
     -m 可将每个节点上系统范围内的内存信息添加到输出。更多信息请参见  
     numastat 手册页。 
    8.4.1. NUMA 虚拟 CPU 钉选
numatune 可以避免 NUMA 缺失。NUMA 缺失会对性能带来显著影响,通常会有至少 10% 或更多的性能损失。虚拟 CPU 钉选和  
    numatune 应该同时配置。 
   注意
重要
<vcpu cpuset='0-7'>8</vcpu>
        <cputune>
                <vcpupin vcpu='0' cpuset='0'/>
                <vcpupin vcpu='1' cpuset='1'/>
                <vcpupin vcpu='2' cpuset='2'/>
                <vcpupin vcpu='3' cpuset='3'/>
                <vcpupin vcpu='4' cpuset='4'/>
                <vcpupin vcpu='5' cpuset='5'/>
                <vcpupin vcpu='6' cpuset='6'/>
                <vcpupin vcpu='7' cpuset='7'/>
        </cputune> 
   <vcpupin> 。进而,vCPU5 将会被固定在物理 CPU 0-7 上,正如上一级标签 <vcpu> 中指定的那样: 
   <vcpu cpuset='0-7'>8</vcpu>
        <cputune>
                <vcpupin vcpu='0' cpuset='0'/>
                <vcpupin vcpu='1' cpuset='1'/>
                <vcpupin vcpu='2' cpuset='2'/>
                <vcpupin vcpu='3' cpuset='3'/>
                <vcpupin vcpu='4' cpuset='4'/>
                <vcpupin vcpu='6' cpuset='6'/>
                <vcpupin vcpu='7' cpuset='7'/>
        </cputune> 
   重要
<vcpupin>、 
      <numatune> 以及  
      <emulatorpin> 应该被一同配置,从而实现优化、确定的性能。更多关于  
      <numatune> 标签的信息,请查看 
      第 8.4.2 节 “域进程”。更多关于  
      <emulatorpin> 标签的信息,请参照 
      第 8.4.4 节 “使用 emulatorpin”。 
     8.4.2. 域进程
<numatune> 标签内部的示例,请参考以下 XML 配置: 
   <numatune>
        <memory mode='strict' placement='auto'/>
</numatune> 
   <numatune>
        <memory mode='strict' nodeset='0,2-3'/>
</numatune> 
   <vcpu> 标签内部的示例,请参考以下 XML 配置: 
   <vcpu placement='auto'>8</vcpu>
<vcpu placement='static' cpuset='0-10,ˆ5'>8</vcpu>
<vcpu> 所使用的放置模式和  
    <numatune> 之间有隐式的继承规则: 
   -  
      
<numatune>的放置模式默认为与<vcpu>相同的放置模式,当<nodeset>被指定时,则被默认为 static。 -  
      同样,
<vcpu>的放置模式默认为与<numatune>相同的放置模式,当<cpuset>被指定时,则被默认为 static。 
<vcpu placement='auto' current='8'>32</vcpu>
注意
8.4.3. 域虚拟 CPU 线程
<cputune> 标签内部每个虚拟 CPU 线程的钉选策略: 
   <cputune>
        <vcpupin vcpu="0" cpuset="1-4,ˆ2"/>
        <vcpupin vcpu="1" cpuset="0,1"/>
        <vcpupin vcpu="2" cpuset="2,3"/>
        <vcpupin vcpu="3" cpuset="0,4"/>
</cputune> 
   注意
<cputune> 的信息,请参照以下网址:  
      http://libvirt.org/formatdomain.html#elementsCPUTuning 
     8.4.4. 使用 emulatorpin
<cputune> 中的  
    <emulatorpin> 标签。 
   <emulatorpin> 标签指定了  
    emulator(一个域的子集,不包括虚拟 CPU)将被固定的主机物理 CPU。<emulatorpin> 标签提供了一个将精确关联设定成仿真线程进程的方法。因此,vhost 线程在同一个物理 CPU 和内存子集中运行,从而可以从缓存位置获益。例如: 
   <cputune>
        <emulatorpin cpuset="1-3"/>
</cputune> 
   注意
<emulatorpin> 的需要。关于自动化 NUMA 平衡的更多信息,请参照 
      第 8.3 节 “自动化 NUMA 平衡”。 
     8.4.5. 用 virsh 调试 vcpu CPU 钉选
重要
virsh 命令会将 ID 为 1 的虚拟 CPU 线程( 
    rhel7)固定到物理 CPU 2。 
   % virsh vcpupin rhel7 1 2
virsh 命令获得当前虚拟 CPU 的钉选配置。例如: 
   % virsh vcpupin rhel7
8.4.6. 用 virsh 调试域进程 CPU 钉选
重要
emulatorpin 选项将 CPU 关联设置应用到与每个域进程关联的线程。为了完全固定,您必须给每个客机同时使用  
    virsh vcpupin(如之前所展示的)和  
    virsh emulatorpin。例如: 
   % virsh emulatorpin rhel7 3-4
8.4.7. 用 virsh 调试域进程内存策略
% virsh numatune rhel7 --nodeset 0-10
virsh 手册页。 
   8.4.8. 客机 NUMA 拓扑
<cpu> 标签中的  
    <numa> 标签在客机虚拟机的 XML 中进行指定。请参照以下示例,并替换相应的属性值: 
   <cpu>
        ...
    <numa>
      <cell cpus='0-3' memory='512000'/>
      <cell cpus='4-7' memory='512000'/>
    </numa>
    ...
</cpu> 
   <cell> 元素指定一个 NUMA cell 或者 NUMA 节点。 
    cpus 指定了 CPU 或者部分节点的系列 CPU, 
    memory 以千位字节(1,024字节一块)指定了节点内存。从 0 开始, 
    cellid 或  
    nodeid 以递增的次序被指定到每个 cell 或节点。 
   8.4.9. 向多个客机 NUMA 节点指定主机大页面
<memoryBacking> 元素中指定大页面的大小和客机 NUMA 节点集。 
    page size 和  
    unit 代表主机大页面的大小。 
    nodeset 指定了大页面被分配的客机 NUMA 节点(或若干节点)。 
   <memoryBacking>
        <hugepages/>
          <page size="1" unit="G" nodeset="0-3,5"/>
          <page size="2" unit="M" nodeset="4"/>
        </hugepages>
</memoryBacking> 
   注意
strict 内存模式时,在 NUMA 节点上不具有足够可用的大页面的情况下,客机将无法启用。关于  
      <numatune> 标签中  
      strict 内存模式选项的配置示例,请参照 
      第 8.4.2 节 “域进程”。 
     8.4.10. PCI 设备的 NUMA 节点位置
/sys/devices/pci*/*/numa_node 的  
    sysfs 文件中可见。使用  
    lstopo 工具来回报 sysfs 数据,可以作为验证这些设置的一种方法。 
   # lstopo-no-graphics 
Machine (126GB)
  NUMANode L#0 (P#0 63GB)
    Socket L#0 + L3 L#0 (20MB)
      L2 L#0 (256KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0 + PU L#0 (P#0)
      L2 L#1 (256KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1 + PU L#1 (P#2)
      L2 L#2 (256KB) + L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2 + PU L#2 (P#4)
      L2 L#3 (256KB) + L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3 + PU L#3 (P#6)
      L2 L#4 (256KB) + L1d L#4 (32KB) + L1i L#4 (32KB) + Core L#4 + PU L#4 (P#8)
      L2 L#5 (256KB) + L1d L#5 (32KB) + L1i L#5 (32KB) + Core L#5 + PU L#5 (P#10)
      L2 L#6 (256KB) + L1d L#6 (32KB) + L1i L#6 (32KB) + Core L#6 + PU L#6 (P#12)
      L2 L#7 (256KB) + L1d L#7 (32KB) + L1i L#7 (32KB) + Core L#7 + PU L#7 (P#14)
    HostBridge L#0
      PCIBridge
        PCI 8086:1521
          Net L#0 "em1"
        PCI 8086:1521
          Net L#1 "em2"
        PCI 8086:1521
          Net L#2 "em3"
        PCI 8086:1521
          Net L#3 "em4"
      PCIBridge
        PCI 1000:005b
          Block L#4 "sda"
          Block L#5 "sdb"
          Block L#6 "sdc"
          Block L#7 "sdd"
      PCIBridge
        PCI 8086:154d
          Net L#8 "p3p1"
        PCI 8086:154d
          Net L#9 "p3p2"
      PCIBridge
        PCIBridge
          PCIBridge
            PCIBridge
              PCI 102b:0534
                GPU L#10 "card0"
                GPU L#11 "controlD64"
      PCI 8086:1d02
  NUMANode L#1 (P#1 63GB)
    Socket L#1 + L3 L#1 (20MB)
      L2 L#8 (256KB) + L1d L#8 (32KB) + L1i L#8 (32KB) + Core L#8 + PU L#8 (P#1)
      L2 L#9 (256KB) + L1d L#9 (32KB) + L1i L#9 (32KB) + Core L#9 + PU L#9 (P#3)
      L2 L#10 (256KB) + L1d L#10 (32KB) + L1i L#10 (32KB) + Core L#10 + PU L#10 (P#5)
      L2 L#11 (256KB) + L1d L#11 (32KB) + L1i L#11 (32KB) + Core L#11 + PU L#11 (P#7)
      L2 L#12 (256KB) + L1d L#12 (32KB) + L1i L#12 (32KB) + Core L#12 + PU L#12 (P#9)
      L2 L#13 (256KB) + L1d L#13 (32KB) + L1i L#13 (32KB) + Core L#13 + PU L#13 (P#11)
      L2 L#14 (256KB) + L1d L#14 (32KB) + L1i L#14 (32KB) + Core L#14 + PU L#14 (P#13)
      L2 L#15 (256KB) + L1d L#15 (32KB) + L1i L#15 (32KB) + Core L#15 + PU L#15 (P#15)
    HostBridge L#8
      PCIBridge
        PCI 1924:0903
          Net L#12 "p1p1"
        PCI 1924:0903
          Net L#13 "p1p2"
      PCIBridge
        PCI 15b3:1003
          Net L#14 "ib0"
          Net L#15 "ib1"
          OpenFabrics L#16 "mlx4_0"
 
   -  
       NIC
em*与磁盘sd*是与 NUMA 节点 0 和 cores 0、2、4、6、8、10、12、14 连接的。 -  
       NIC
p1*与ib*是与 NUMA 节点 1 和 cores 1、3、5、7、9、11、13、15 连接的。 
8.5. NUMA-Aware 内核同页合并
sysfs /sys/kernel/mm/ksm/merge_across_nodes 参数来控制不同 NUMA 节点中的页面合并。在默认情况下,所有节点的页面都可以进行合并。当该参数被设置为 0 时,只有来自同一个节点的页面可以合并。 
  重要
<memoryBacking>
         <nosharepages/>
</memoryBacking>
# 
  <memoryBacking> 元素调试内存设置的信息,请参照 
   第 7.3.2 节 “使用 virsh 调试内存”。 
  